summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/asio
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/asio')
-rw-r--r--src/boost/libs/asio/example/cpp03/allocation/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp03/allocation/server.cpp285
-rw-r--r--src/boost/libs/asio/example/cpp03/buffers/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp03/buffers/reference_counted.cpp131
-rw-r--r--src/boost/libs/asio/example/cpp03/chat/Jamfile.v235
-rw-r--r--src/boost/libs/asio/example/cpp03/chat/chat_client.cpp178
-rw-r--r--src/boost/libs/asio/example/cpp03/chat/chat_message.hpp93
-rw-r--r--src/boost/libs/asio/example/cpp03/chat/chat_server.cpp249
-rw-r--r--src/boost/libs/asio/example/cpp03/chat/posix_chat_client.cpp204
-rw-r--r--src/boost/libs/asio/example/cpp03/echo/Jamfile.v238
-rw-r--r--src/boost/libs/asio/example/cpp03/echo/async_tcp_echo_server.cpp137
-rw-r--r--src/boost/libs/asio/example/cpp03/echo/async_udp_echo_server.cpp92
-rw-r--r--src/boost/libs/asio/example/cpp03/echo/blocking_tcp_echo_client.cpp59
-rw-r--r--src/boost/libs/asio/example/cpp03/echo/blocking_tcp_echo_server.cpp80
-rw-r--r--src/boost/libs/asio/example/cpp03/echo/blocking_udp_echo_client.cpp59
-rw-r--r--src/boost/libs/asio/example/cpp03/echo/blocking_udp_echo_server.cpp53
-rw-r--r--src/boost/libs/asio/example/cpp03/fork/Jamfile.v246
-rw-r--r--src/boost/libs/asio/example/cpp03/fork/daemon.cpp190
-rw-r--r--src/boost/libs/asio/example/cpp03/fork/process_per_connection.cpp161
-rw-r--r--src/boost/libs/asio/example/cpp03/http/client/Jamfile.v233
-rw-r--r--src/boost/libs/asio/example/cpp03/http/client/async_client.cpp204
-rw-r--r--src/boost/libs/asio/example/cpp03/http/client/sync_client.cpp106
-rw-r--r--src/boost/libs/asio/example/cpp03/http/doc_root/data_1K.html28
-rw-r--r--src/boost/libs/asio/example/cpp03/http/doc_root/data_2K.html49
-rw-r--r--src/boost/libs/asio/example/cpp03/http/doc_root/data_4K.html91
-rw-r--r--src/boost/libs/asio/example/cpp03/http/doc_root/data_8K.html175
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/Jamfile.v238
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/connection.cpp99
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/connection.hpp83
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/connection_manager.cpp38
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/connection_manager.hpp44
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/header.hpp28
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/main.cpp44
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/mime_types.cpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/mime_types.hpp27
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/reply.cpp256
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/reply.hpp64
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/request.hpp34
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/request_handler.cpp122
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/request_handler.hpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/request_parser.cpp315
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/request_parser.hpp95
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/server.cpp94
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server/server.hpp69
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/Jamfile.v238
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/connection.cpp93
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/connection.hpp75
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/header.hpp28
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/io_context_pool.cpp70
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/io_context_pool.hpp58
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/main.cpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/mime_types.cpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/mime_types.hpp27
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/reply.cpp256
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/reply.hpp64
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/request.hpp34
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/request_handler.cpp122
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/request_handler.hpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/request_parser.cpp315
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/request_parser.hpp95
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/server.cpp77
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server2/server.hpp68
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/Jamfile.v237
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/connection.cpp94
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/connection.hpp78
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/header.hpp28
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/main.cpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/mime_types.cpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/mime_types.hpp27
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/reply.cpp256
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/reply.hpp64
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/request.hpp34
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/request_handler.cpp122
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/request_handler.hpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/request_parser.cpp315
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/request_parser.hpp95
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/server.cpp90
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server3/server.hpp70
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/Jamfile.v236
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/file_handler.cpp122
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/file_handler.hpp44
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/header.hpp28
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/main.cpp58
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/mime_types.cpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/mime_types.hpp27
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/reply.cpp256
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/reply.hpp64
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/request.hpp46
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/request_parser.cpp226
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/request_parser.hpp78
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/server.cpp122
-rw-r--r--src/boost/libs/asio/example/cpp03/http/server4/server.hpp73
-rw-r--r--src/boost/libs/asio/example/cpp03/icmp/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp03/icmp/icmp_header.hpp94
-rw-r--r--src/boost/libs/asio/example/cpp03/icmp/ipv4_header.hpp102
-rw-r--r--src/boost/libs/asio/example/cpp03/icmp/ping.cpp163
-rw-r--r--src/boost/libs/asio/example/cpp03/invocation/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp03/invocation/prioritised_handlers.cpp171
-rw-r--r--src/boost/libs/asio/example/cpp03/iostreams/Jamfile.v234
-rw-r--r--src/boost/libs/asio/example/cpp03/iostreams/daytime_client.cpp44
-rw-r--r--src/boost/libs/asio/example/cpp03/iostreams/daytime_server.cpp51
-rw-r--r--src/boost/libs/asio/example/cpp03/iostreams/http_client.cpp91
-rw-r--r--src/boost/libs/asio/example/cpp03/local/Jamfile.v282
-rw-r--r--src/boost/libs/asio/example/cpp03/local/connect_pair.cpp142
-rw-r--r--src/boost/libs/asio/example/cpp03/local/iostream_client.cpp62
-rw-r--r--src/boost/libs/asio/example/cpp03/local/stream_client.cpp61
-rw-r--r--src/boost/libs/asio/example/cpp03/local/stream_server.cpp141
-rw-r--r--src/boost/libs/asio/example/cpp03/multicast/Jamfile.v233
-rw-r--r--src/boost/libs/asio/example/cpp03/multicast/receiver.cpp93
-rw-r--r--src/boost/libs/asio/example/cpp03/multicast/sender.cpp98
-rw-r--r--src/boost/libs/asio/example/cpp03/nonblocking/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp03/nonblocking/third_party_lib.cpp240
-rw-r--r--src/boost/libs/asio/example/cpp03/porthopper/Jamfile.v233
-rw-r--r--src/boost/libs/asio/example/cpp03/porthopper/client.cpp192
-rw-r--r--src/boost/libs/asio/example/cpp03/porthopper/protocol.hpp156
-rw-r--r--src/boost/libs/asio/example/cpp03/porthopper/server.cpp187
-rw-r--r--src/boost/libs/asio/example/cpp03/serialization/Jamfile.v234
-rw-r--r--src/boost/libs/asio/example/cpp03/serialization/client.cpp125
-rw-r--r--src/boost/libs/asio/example/cpp03/serialization/connection.hpp188
-rw-r--r--src/boost/libs/asio/example/cpp03/serialization/server.cpp123
-rw-r--r--src/boost/libs/asio/example/cpp03/serialization/stock.hpp50
-rw-r--r--src/boost/libs/asio/example/cpp03/services/Jamfile.v232
-rw-r--r--src/boost/libs/asio/example/cpp03/services/basic_logger.hpp83
-rw-r--r--src/boost/libs/asio/example/cpp03/services/daytime_client.cpp97
-rw-r--r--src/boost/libs/asio/example/cpp03/services/logger.hpp24
-rw-r--r--src/boost/libs/asio/example/cpp03/services/logger_service.cpp11
-rw-r--r--src/boost/libs/asio/example/cpp03/services/logger_service.hpp146
-rw-r--r--src/boost/libs/asio/example/cpp03/socks4/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp03/socks4/socks4.hpp144
-rw-r--r--src/boost/libs/asio/example/cpp03/socks4/sync_client.cpp94
-rw-r--r--src/boost/libs/asio/example/cpp03/spawn/Jamfile.v250
-rw-r--r--src/boost/libs/asio/example/cpp03/spawn/echo_server.cpp122
-rw-r--r--src/boost/libs/asio/example/cpp03/spawn/parallel_grep.cpp90
-rw-r--r--src/boost/libs/asio/example/cpp03/ssl/Jamfile.v248
-rw-r--r--src/boost/libs/asio/example/cpp03/ssl/README8
-rw-r--r--src/boost/libs/asio/example/cpp03/ssl/ca.pem49
-rw-r--r--src/boost/libs/asio/example/cpp03/ssl/client.cpp157
-rw-r--r--src/boost/libs/asio/example/cpp03/ssl/dh2048.pem8
-rw-r--r--src/boost/libs/asio/example/cpp03/ssl/server.cpp170
-rw-r--r--src/boost/libs/asio/example/cpp03/ssl/server.pem71
-rw-r--r--src/boost/libs/asio/example/cpp03/timeouts/Jamfile.v236
-rw-r--r--src/boost/libs/asio/example/cpp03/timeouts/async_tcp_client.cpp311
-rw-r--r--src/boost/libs/asio/example/cpp03/timeouts/blocking_tcp_client.cpp191
-rw-r--r--src/boost/libs/asio/example/cpp03/timeouts/blocking_token_tcp_client.cpp202
-rw-r--r--src/boost/libs/asio/example/cpp03/timeouts/blocking_udp_client.cpp154
-rw-r--r--src/boost/libs/asio/example/cpp03/timeouts/server.cpp433
-rw-r--r--src/boost/libs/asio/example/cpp03/timers/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp03/timers/time_t_timer.cpp106
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/Jamfile.v267
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/daytime1/client.cpp57
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/daytime2/server.cpp50
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/daytime3/server.cpp119
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/daytime4/client.cpp52
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/daytime5/server.cpp53
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/daytime6/server.cpp89
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/daytime7/server.cpp160
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/daytime_dox.txt500
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/index_dox.txt48
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/timer1/timer.cpp24
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/timer2/timer.cpp29
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/timer3/timer.cpp43
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/timer4/timer.cpp54
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/timer5/timer.cpp81
-rw-r--r--src/boost/libs/asio/example/cpp03/tutorial/timer_dox.txt378
-rw-r--r--src/boost/libs/asio/example/cpp03/windows/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp03/windows/transmit_file.cpp177
-rw-r--r--src/boost/libs/asio/example/cpp11/allocation/Jamfile.v229
-rw-r--r--src/boost/libs/asio/example/cpp11/allocation/server.cpp255
-rw-r--r--src/boost/libs/asio/example/cpp11/buffers/Jamfile.v229
-rw-r--r--src/boost/libs/asio/example/cpp11/buffers/reference_counted.cpp122
-rw-r--r--src/boost/libs/asio/example/cpp11/chat/Jamfile.v233
-rw-r--r--src/boost/libs/asio/example/cpp11/chat/chat_client.cpp167
-rw-r--r--src/boost/libs/asio/example/cpp11/chat/chat_message.hpp91
-rw-r--r--src/boost/libs/asio/example/cpp11/chat/chat_server.cpp227
-rw-r--r--src/boost/libs/asio/example/cpp11/echo/Jamfile.v237
-rw-r--r--src/boost/libs/asio/example/cpp11/echo/async_tcp_echo_server.cpp114
-rw-r--r--src/boost/libs/asio/example/cpp11/echo/async_udp_echo_server.cpp82
-rw-r--r--src/boost/libs/asio/example/cpp11/echo/blocking_tcp_echo_client.cpp55
-rw-r--r--src/boost/libs/asio/example/cpp11/echo/blocking_tcp_echo_server.cpp74
-rw-r--r--src/boost/libs/asio/example/cpp11/echo/blocking_udp_echo_client.cpp58
-rw-r--r--src/boost/libs/asio/example/cpp11/echo/blocking_udp_echo_server.cpp52
-rw-r--r--src/boost/libs/asio/example/cpp11/executors/Jamfile.v236
-rw-r--r--src/boost/libs/asio/example/cpp11/executors/actor.cpp286
-rw-r--r--src/boost/libs/asio/example/cpp11/executors/bank_account_1.cpp54
-rw-r--r--src/boost/libs/asio/example/cpp11/executors/bank_account_2.cpp54
-rw-r--r--src/boost/libs/asio/example/cpp11/executors/fork_join.cpp328
-rw-r--r--src/boost/libs/asio/example/cpp11/executors/pipeline.cpp299
-rw-r--r--src/boost/libs/asio/example/cpp11/executors/priority_scheduler.cpp174
-rw-r--r--src/boost/libs/asio/example/cpp11/fork/Jamfile.v245
-rw-r--r--src/boost/libs/asio/example/cpp11/fork/daemon.cpp189
-rw-r--r--src/boost/libs/asio/example/cpp11/fork/process_per_connection.cpp162
-rw-r--r--src/boost/libs/asio/example/cpp11/futures/Jamfile.v229
-rw-r--r--src/boost/libs/asio/example/cpp11/futures/daytime_client.cpp94
-rw-r--r--src/boost/libs/asio/example/cpp11/handler_tracking/Jamfile.v231
-rw-r--r--src/boost/libs/asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp114
-rw-r--r--src/boost/libs/asio/example/cpp11/handler_tracking/custom_tracking.hpp201
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/Jamfile.v237
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/connection.cpp94
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/connection.hpp79
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/connection_manager.cpp40
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/connection_manager.hpp48
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/header.hpp28
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/main.cpp43
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/mime_types.cpp45
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/mime_types.hpp27
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/reply.cpp255
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/reply.hpp64
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/request.hpp34
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/request_handler.cpp121
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/request_handler.hpp47
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/request_parser.cpp315
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/request_parser.hpp96
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/server.cpp94
-rw-r--r--src/boost/libs/asio/example/cpp11/http/server/server.hpp64
-rw-r--r--src/boost/libs/asio/example/cpp11/invocation/Jamfile.v229
-rw-r--r--src/boost/libs/asio/example/cpp11/invocation/prioritised_handlers.cpp202
-rw-r--r--src/boost/libs/asio/example/cpp11/iostreams/Jamfile.v231
-rw-r--r--src/boost/libs/asio/example/cpp11/iostreams/http_client.cpp91
-rw-r--r--src/boost/libs/asio/example/cpp11/local/Jamfile.v278
-rw-r--r--src/boost/libs/asio/example/cpp11/local/connect_pair.cpp130
-rw-r--r--src/boost/libs/asio/example/cpp11/local/iostream_client.cpp61
-rw-r--r--src/boost/libs/asio/example/cpp11/local/stream_client.cpp60
-rw-r--r--src/boost/libs/asio/example/cpp11/local/stream_server.cpp121
-rw-r--r--src/boost/libs/asio/example/cpp11/multicast/Jamfile.v232
-rw-r--r--src/boost/libs/asio/example/cpp11/multicast/receiver.cpp88
-rw-r--r--src/boost/libs/asio/example/cpp11/multicast/sender.cpp91
-rw-r--r--src/boost/libs/asio/example/cpp11/nonblocking/Jamfile.v229
-rw-r--r--src/boost/libs/asio/example/cpp11/nonblocking/third_party_lib.cpp212
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/Jamfile.v239
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/composed_1.cpp113
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/composed_2.cpp131
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/composed_3.cpp192
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/composed_4.cpp207
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/composed_5.cpp243
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/composed_6.cpp302
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/composed_7.cpp222
-rw-r--r--src/boost/libs/asio/example/cpp11/operations/composed_8.cpp217
-rw-r--r--src/boost/libs/asio/example/cpp11/socks4/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp11/socks4/socks4.hpp143
-rw-r--r--src/boost/libs/asio/example/cpp11/socks4/sync_client.cpp93
-rw-r--r--src/boost/libs/asio/example/cpp11/spawn/Jamfile.v231
-rw-r--r--src/boost/libs/asio/example/cpp11/spawn/echo_server.cpp111
-rw-r--r--src/boost/libs/asio/example/cpp11/spawn/parallel_grep.cpp84
-rw-r--r--src/boost/libs/asio/example/cpp11/ssl/Jamfile.v248
-rw-r--r--src/boost/libs/asio/example/cpp11/ssl/README8
-rw-r--r--src/boost/libs/asio/example/cpp11/ssl/ca.pem49
-rw-r--r--src/boost/libs/asio/example/cpp11/ssl/client.cpp165
-rw-r--r--src/boost/libs/asio/example/cpp11/ssl/dh2048.pem8
-rw-r--r--src/boost/libs/asio/example/cpp11/ssl/server.cpp143
-rw-r--r--src/boost/libs/asio/example/cpp11/ssl/server.pem71
-rw-r--r--src/boost/libs/asio/example/cpp11/timeouts/Jamfile.v236
-rw-r--r--src/boost/libs/asio/example/cpp11/timeouts/async_tcp_client.cpp311
-rw-r--r--src/boost/libs/asio/example/cpp11/timeouts/blocking_tcp_client.cpp192
-rw-r--r--src/boost/libs/asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp199
-rw-r--r--src/boost/libs/asio/example/cpp11/timeouts/blocking_udp_client.cpp155
-rw-r--r--src/boost/libs/asio/example/cpp11/timeouts/server.cpp433
-rw-r--r--src/boost/libs/asio/example/cpp11/timers/Jamfile.v230
-rw-r--r--src/boost/libs/asio/example/cpp11/timers/time_t_timer.cpp106
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/Jamfile.v238
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/actor.cpp281
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/async_1.cpp47
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/async_2.cpp68
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/bank_account_1.cpp54
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/bank_account_2.cpp53
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/fork_join.cpp327
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/pipeline.cpp294
-rw-r--r--src/boost/libs/asio/example/cpp14/executors/priority_scheduler.cpp173
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/Jamfile.v239
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/composed_1.cpp113
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/composed_2.cpp131
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/composed_3.cpp186
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/composed_4.cpp201
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/composed_5.cpp238
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/composed_6.cpp298
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/composed_7.cpp219
-rw-r--r--src/boost/libs/asio/example/cpp14/operations/composed_8.cpp212
-rw-r--r--src/boost/libs/asio/example/cpp17/coroutines_ts/chat_server.cpp225
-rw-r--r--src/boost/libs/asio/example/cpp17/coroutines_ts/echo_server.cpp76
-rw-r--r--src/boost/libs/asio/example/cpp17/coroutines_ts/echo_server_with_default.cpp78
-rw-r--r--src/boost/libs/asio/example/cpp17/coroutines_ts/range_based_for.cpp107
-rw-r--r--src/boost/libs/asio/example/cpp17/coroutines_ts/refactored_echo_server.cpp85
-rw-r--r--src/boost/libs/asio/index.html21
-rw-r--r--src/boost/libs/asio/meta/libraries.json15
-rw-r--r--src/boost/libs/asio/test/Jamfile.v2235
-rw-r--r--src/boost/libs/asio/test/archetypes/async_ops.hpp415
-rw-r--r--src/boost/libs/asio/test/archetypes/async_result.hpp96
-rw-r--r--src/boost/libs/asio/test/archetypes/gettable_socket_option.hpp54
-rw-r--r--src/boost/libs/asio/test/archetypes/io_control_command.hpp32
-rw-r--r--src/boost/libs/asio/test/archetypes/settable_socket_option.hpp49
-rw-r--r--src/boost/libs/asio/test/associated_allocator.cpp25
-rw-r--r--src/boost/libs/asio/test/associated_executor.cpp25
-rw-r--r--src/boost/libs/asio/test/async_result.cpp25
-rw-r--r--src/boost/libs/asio/test/awaitable.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_datagram_socket.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_deadline_timer.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_raw_socket.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_seq_packet_socket.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_serial_port.cpp26
-rw-r--r--src/boost/libs/asio/test/basic_signal_set.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_socket.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_socket_acceptor.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_stream_socket.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_streambuf.cpp25
-rw-r--r--src/boost/libs/asio/test/basic_waitable_timer.cpp25
-rw-r--r--src/boost/libs/asio/test/bind_executor.cpp25
-rw-r--r--src/boost/libs/asio/test/buffer.cpp830
-rw-r--r--src/boost/libs/asio/test/buffered_read_stream.cpp338
-rw-r--r--src/boost/libs/asio/test/buffered_stream.cpp364
-rw-r--r--src/boost/libs/asio/test/buffered_write_stream.cpp353
-rw-r--r--src/boost/libs/asio/test/buffers_iterator.cpp292
-rw-r--r--src/boost/libs/asio/test/co_spawn.cpp25
-rw-r--r--src/boost/libs/asio/test/completion_condition.cpp25
-rw-r--r--src/boost/libs/asio/test/compose.cpp185
-rw-r--r--src/boost/libs/asio/test/connect.cpp1190
-rw-r--r--src/boost/libs/asio/test/coroutine.cpp112
-rw-r--r--src/boost/libs/asio/test/deadline_timer.cpp392
-rw-r--r--src/boost/libs/asio/test/defer.cpp25
-rw-r--r--src/boost/libs/asio/test/detached.cpp25
-rw-r--r--src/boost/libs/asio/test/dispatch.cpp25
-rw-r--r--src/boost/libs/asio/test/error.cpp89
-rw-r--r--src/boost/libs/asio/test/execution_context.cpp25
-rw-r--r--src/boost/libs/asio/test/executor.cpp25
-rw-r--r--src/boost/libs/asio/test/executor_work_guard.cpp25
-rw-r--r--src/boost/libs/asio/test/generic/basic_endpoint.cpp25
-rw-r--r--src/boost/libs/asio/test/generic/datagram_protocol.cpp263
-rw-r--r--src/boost/libs/asio/test/generic/raw_protocol.cpp263
-rw-r--r--src/boost/libs/asio/test/generic/seq_packet_protocol.cpp205
-rw-r--r--src/boost/libs/asio/test/generic/stream_protocol.cpp248
-rw-r--r--src/boost/libs/asio/test/high_resolution_timer.cpp30
-rw-r--r--src/boost/libs/asio/test/io_context.cpp362
-rw-r--r--src/boost/libs/asio/test/io_context_strand.cpp325
-rw-r--r--src/boost/libs/asio/test/ip/address.cpp144
-rw-r--r--src/boost/libs/asio/test/ip/address_v4.cpp324
-rw-r--r--src/boost/libs/asio/test/ip/address_v4_iterator.cpp27
-rw-r--r--src/boost/libs/asio/test/ip/address_v4_range.cpp27
-rw-r--r--src/boost/libs/asio/test/ip/address_v6.cpp409
-rw-r--r--src/boost/libs/asio/test/ip/address_v6_iterator.cpp27
-rw-r--r--src/boost/libs/asio/test/ip/address_v6_range.cpp27
-rw-r--r--src/boost/libs/asio/test/ip/basic_endpoint.cpp25
-rw-r--r--src/boost/libs/asio/test/ip/basic_resolver.cpp25
-rw-r--r--src/boost/libs/asio/test/ip/basic_resolver_entry.cpp25
-rw-r--r--src/boost/libs/asio/test/ip/basic_resolver_iterator.cpp25
-rw-r--r--src/boost/libs/asio/test/ip/basic_resolver_query.cpp25
-rw-r--r--src/boost/libs/asio/test/ip/host_name.cpp55
-rw-r--r--src/boost/libs/asio/test/ip/icmp.cpp577
-rw-r--r--src/boost/libs/asio/test/ip/multicast.cpp363
-rw-r--r--src/boost/libs/asio/test/ip/network_v4.cpp314
-rw-r--r--src/boost/libs/asio/test/ip/network_v6.cpp238
-rw-r--r--src/boost/libs/asio/test/ip/resolver_query_base.cpp25
-rw-r--r--src/boost/libs/asio/test/ip/tcp.cpp1346
-rw-r--r--src/boost/libs/asio/test/ip/udp.cpp673
-rw-r--r--src/boost/libs/asio/test/ip/unicast.cpp171
-rw-r--r--src/boost/libs/asio/test/ip/v6_only.cpp135
-rw-r--r--src/boost/libs/asio/test/is_read_buffered.cpp129
-rw-r--r--src/boost/libs/asio/test/is_write_buffered.cpp129
-rw-r--r--src/boost/libs/asio/test/latency/Jamfile.v236
-rw-r--r--src/boost/libs/asio/test/latency/allocator.hpp52
-rw-r--r--src/boost/libs/asio/test/latency/high_res_clock.hpp53
-rw-r--r--src/boost/libs/asio/test/latency/tcp_client.cpp124
-rw-r--r--src/boost/libs/asio/test/latency/tcp_server.cpp114
-rw-r--r--src/boost/libs/asio/test/latency/udp_client.cpp104
-rw-r--r--src/boost/libs/asio/test/latency/udp_server.cpp125
-rw-r--r--src/boost/libs/asio/test/local/basic_endpoint.cpp25
-rw-r--r--src/boost/libs/asio/test/local/connect_pair.cpp76
-rw-r--r--src/boost/libs/asio/test/local/datagram_protocol.cpp242
-rw-r--r--src/boost/libs/asio/test/local/stream_protocol.cpp219
-rw-r--r--src/boost/libs/asio/test/packaged_task.cpp25
-rw-r--r--src/boost/libs/asio/test/placeholders.cpp25
-rw-r--r--src/boost/libs/asio/test/posix/basic_descriptor.cpp25
-rw-r--r--src/boost/libs/asio/test/posix/basic_stream_descriptor.cpp25
-rw-r--r--src/boost/libs/asio/test/posix/descriptor.cpp25
-rw-r--r--src/boost/libs/asio/test/posix/descriptor_base.cpp25
-rw-r--r--src/boost/libs/asio/test/posix/stream_descriptor.cpp183
-rw-r--r--src/boost/libs/asio/test/post.cpp25
-rw-r--r--src/boost/libs/asio/test/read.cpp4997
-rw-r--r--src/boost/libs/asio/test/read_at.cpp7502
-rw-r--r--src/boost/libs/asio/test/read_until.cpp1660
-rw-r--r--src/boost/libs/asio/test/redirect_error.cpp25
-rw-r--r--src/boost/libs/asio/test/serial_port.cpp173
-rw-r--r--src/boost/libs/asio/test/serial_port_base.cpp99
-rw-r--r--src/boost/libs/asio/test/signal_set.cpp95
-rw-r--r--src/boost/libs/asio/test/socket_base.cpp650
-rw-r--r--src/boost/libs/asio/test/ssl/Jamfile.v260
-rw-r--r--src/boost/libs/asio/test/ssl/context.cpp25
-rw-r--r--src/boost/libs/asio/test/ssl/context_base.cpp25
-rw-r--r--src/boost/libs/asio/test/ssl/error.cpp25
-rw-r--r--src/boost/libs/asio/test/ssl/host_name_verification.cpp25
-rw-r--r--src/boost/libs/asio/test/ssl/rfc2818_verification.cpp25
-rw-r--r--src/boost/libs/asio/test/ssl/stream.cpp191
-rw-r--r--src/boost/libs/asio/test/ssl/stream_base.cpp25
-rw-r--r--src/boost/libs/asio/test/steady_timer.cpp30
-rw-r--r--src/boost/libs/asio/test/strand.cpp263
-rw-r--r--src/boost/libs/asio/test/streambuf.cpp62
-rw-r--r--src/boost/libs/asio/test/system_context.cpp30
-rw-r--r--src/boost/libs/asio/test/system_executor.cpp30
-rw-r--r--src/boost/libs/asio/test/system_timer.cpp399
-rw-r--r--src/boost/libs/asio/test/this_coro.cpp25
-rw-r--r--src/boost/libs/asio/test/time_traits.cpp25
-rw-r--r--src/boost/libs/asio/test/ts/buffer.cpp30
-rw-r--r--src/boost/libs/asio/test/ts/executor.cpp30
-rw-r--r--src/boost/libs/asio/test/ts/internet.cpp30
-rw-r--r--src/boost/libs/asio/test/ts/io_context.cpp30
-rw-r--r--src/boost/libs/asio/test/ts/net.cpp30
-rw-r--r--src/boost/libs/asio/test/ts/netfwd.cpp33
-rw-r--r--src/boost/libs/asio/test/ts/socket.cpp30
-rw-r--r--src/boost/libs/asio/test/ts/timer.cpp30
-rw-r--r--src/boost/libs/asio/test/unit_test.hpp177
-rw-r--r--src/boost/libs/asio/test/use_awaitable.cpp25
-rw-r--r--src/boost/libs/asio/test/use_future.cpp670
-rw-r--r--src/boost/libs/asio/test/uses_executor.cpp25
-rw-r--r--src/boost/libs/asio/test/wait_traits.cpp25
-rw-r--r--src/boost/libs/asio/test/windows/basic_object_handle.cpp25
-rw-r--r--src/boost/libs/asio/test/windows/basic_overlapped_handle.cpp25
-rw-r--r--src/boost/libs/asio/test/windows/basic_random_access_handle.cpp25
-rw-r--r--src/boost/libs/asio/test/windows/basic_stream_handle.cpp25
-rw-r--r--src/boost/libs/asio/test/windows/object_handle.cpp130
-rw-r--r--src/boost/libs/asio/test/windows/overlapped_handle.cpp26
-rw-r--r--src/boost/libs/asio/test/windows/overlapped_ptr.cpp107
-rw-r--r--src/boost/libs/asio/test/windows/random_access_handle.cpp155
-rw-r--r--src/boost/libs/asio/test/windows/stream_handle.cpp148
-rw-r--r--src/boost/libs/asio/test/write.cpp4904
-rw-r--r--src/boost/libs/asio/test/write_at.cpp7563
-rwxr-xr-xsrc/boost/libs/asio/tools/handlerviz.pl299
423 files changed, 75600 insertions, 0 deletions
diff --git a/src/boost/libs/asio/example/cpp03/allocation/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/allocation/Jamfile.v2
new file mode 100644
index 000000000..f47511bdb
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/allocation/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : server.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/allocation/server.cpp b/src/boost/libs/asio/example/cpp03/allocation/server.cpp
new file mode 100644
index 000000000..7a0e4966f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/allocation/server.cpp
@@ -0,0 +1,285 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/aligned_storage.hpp>
+#include <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+// Class to manage the memory to be used for handler-based custom allocation.
+// It contains a single block of memory which may be returned for allocation
+// requests. If the memory is in use when an allocation request is made, the
+// allocator delegates allocation to the global heap.
+class handler_memory
+ : private boost::noncopyable
+{
+public:
+ handler_memory()
+ : in_use_(false)
+ {
+ }
+
+ void* allocate(std::size_t size)
+ {
+ if (!in_use_ && size < storage_.size)
+ {
+ in_use_ = true;
+ return storage_.address();
+ }
+ else
+ {
+ return ::operator new(size);
+ }
+ }
+
+ void deallocate(void* pointer)
+ {
+ if (pointer == storage_.address())
+ {
+ in_use_ = false;
+ }
+ else
+ {
+ ::operator delete(pointer);
+ }
+ }
+
+private:
+ // Storage space used for handler-based custom memory allocation.
+ boost::aligned_storage<1024> storage_;
+
+ // Whether the handler-based custom allocation storage has been used.
+ bool in_use_;
+};
+
+// The allocator to be associated with the handler objects. This allocator only
+// needs to satisfy the C++11 minimal allocator requirements, plus rebind when
+// targeting C++03.
+template <typename T>
+class handler_allocator
+{
+public:
+ typedef T value_type;
+
+ explicit handler_allocator(handler_memory& mem)
+ : memory_(mem)
+ {
+ }
+
+ template <typename U>
+ handler_allocator(const handler_allocator<U>& other)
+ : memory_(other.memory_)
+ {
+ }
+
+ template <typename U>
+ struct rebind
+ {
+ typedef handler_allocator<U> other;
+ };
+
+ bool operator==(const handler_allocator& other) const
+ {
+ return &memory_ == &other.memory_;
+ }
+
+ bool operator!=(const handler_allocator& other) const
+ {
+ return &memory_ != &other.memory_;
+ }
+
+ T* allocate(std::size_t n) const
+ {
+ return static_cast<T*>(memory_.allocate(sizeof(T) * n));
+ }
+
+ void deallocate(T* p, std::size_t /*n*/) const
+ {
+ return memory_.deallocate(p);
+ }
+
+//private:
+ // The underlying memory.
+ handler_memory& memory_;
+};
+
+// Wrapper class template for handler objects to allow handler memory
+// allocation to be customised. The allocator_type typedef 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:
+ typedef handler_allocator<Handler> allocator_type;
+
+ custom_alloc_handler(handler_memory& m, Handler h)
+ : memory_(m),
+ handler_(h)
+ {
+ }
+
+ allocator_type get_allocator() const
+ {
+ return allocator_type(memory_);
+ }
+
+ template <typename Arg1>
+ void operator()(Arg1 arg1)
+ {
+ handler_(arg1);
+ }
+
+ template <typename Arg1, typename Arg2>
+ void operator()(Arg1 arg1, Arg2 arg2)
+ {
+ handler_(arg1, arg2);
+ }
+
+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 boost::enable_shared_from_this<session>
+{
+public:
+ session(boost::asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ socket_.async_read_some(boost::asio::buffer(data_),
+ make_custom_alloc_handler(handler_memory_,
+ boost::bind(&session::handle_read,
+ shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred)));
+ }
+
+ void handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(data_, bytes_transferred),
+ make_custom_alloc_handler(handler_memory_,
+ boost::bind(&session::handle_write,
+ shared_from_this(),
+ boost::asio::placeholders::error)));
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ socket_.async_read_some(boost::asio::buffer(data_),
+ make_custom_alloc_handler(handler_memory_,
+ boost::bind(&session::handle_read,
+ shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred)));
+ }
+ }
+
+private:
+ // The socket used to communicate with the client.
+ tcp::socket socket_;
+
+ // Buffer used to store data received from the client.
+ boost::array<char, 1024> data_;
+
+ // The memory to use for handler-based custom memory allocation.
+ handler_memory handler_memory_;
+};
+
+typedef boost::shared_ptr<session> session_ptr;
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : io_context_(io_context),
+ acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
+ {
+ session_ptr new_session(new session(io_context_));
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(session_ptr new_session,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_session->start();
+ }
+
+ new_session.reset(new session(io_context_));
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: server <port>\n";
+ return 1;
+ }
+
+ boost::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() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/buffers/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/buffers/Jamfile.v2
new file mode 100644
index 000000000..f8dde7d80
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/buffers/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : reference_counted.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/buffers/reference_counted.cpp b/src/boost/libs/asio/example/cpp03/buffers/reference_counted.cpp
new file mode 100644
index 000000000..d43e27ff4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/buffers/reference_counted.cpp
@@ -0,0 +1,131 @@
+//
+// reference_counted.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+#include <iostream>
+#include <vector>
+
+using boost::asio::ip::tcp;
+
+// A reference-counted non-modifiable buffer class.
+class shared_const_buffer
+{
+public:
+ // Construct from a std::string.
+ explicit shared_const_buffer(const std::string& data)
+ : data_(new std::vector<char>(data.begin(), data.end())),
+ buffer_(boost::asio::buffer(*data_))
+ {
+ }
+
+ // Implement the ConstBufferSequence requirements.
+ typedef boost::asio::const_buffer value_type;
+ typedef const boost::asio::const_buffer* const_iterator;
+ const boost::asio::const_buffer* begin() const { return &buffer_; }
+ const boost::asio::const_buffer* end() const { return &buffer_ + 1; }
+
+private:
+ boost::shared_ptr<std::vector<char> > data_;
+ boost::asio::const_buffer buffer_;
+};
+
+class session
+ : public boost::enable_shared_from_this<session>
+{
+public:
+ session(boost::asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ using namespace std; // For time_t, time and ctime.
+ time_t now = time(0);
+ shared_const_buffer buffer(ctime(&now));
+ boost::asio::async_write(socket_, buffer,
+ boost::bind(&session::handle_write, shared_from_this()));
+ }
+
+ void handle_write()
+ {
+ }
+
+private:
+ // The socket used to communicate with the client.
+ tcp::socket socket_;
+};
+
+typedef boost::shared_ptr<session> session_ptr;
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : io_context_(io_context),
+ acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
+ {
+ session_ptr new_session(new session(io_context_));
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(session_ptr new_session,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_session->start();
+ }
+
+ new_session.reset(new session(io_context_));
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: reference_counted <port>\n";
+ return 1;
+ }
+
+ boost::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() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/chat/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/chat/Jamfile.v2
new file mode 100644
index 000000000..342bbdcd4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/chat/Jamfile.v2
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe chat_server : chat_server.cpp ;
+exe chat_client : chat_client.cpp ;
+exe posix_chat_client : posix_chat_client.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/chat/chat_client.cpp b/src/boost/libs/asio/example/cpp03/chat/chat_client.cpp
new file mode 100644
index 000000000..08b310066
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/chat/chat_client.cpp
@@ -0,0 +1,178 @@
+//
+// chat_client.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <deque>
+#include <iostream>
+#include <boost/bind/bind.hpp>
+#include <boost/asio.hpp>
+#include <boost/thread/thread.hpp>
+#include "chat_message.hpp"
+
+using boost::asio::ip::tcp;
+
+typedef std::deque<chat_message> chat_message_queue;
+
+class chat_client
+{
+public:
+ chat_client(boost::asio::io_context& io_context,
+ const tcp::resolver::results_type& endpoints)
+ : io_context_(io_context),
+ socket_(io_context)
+ {
+ boost::asio::async_connect(socket_, endpoints,
+ boost::bind(&chat_client::handle_connect, this,
+ boost::asio::placeholders::error));
+ }
+
+ void write(const chat_message& msg)
+ {
+ boost::asio::post(io_context_,
+ boost::bind(&chat_client::do_write, this, msg));
+ }
+
+ void close()
+ {
+ boost::asio::post(io_context_,
+ boost::bind(&chat_client::do_close, this));
+ }
+
+private:
+
+ void handle_connect(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ boost::bind(&chat_client::handle_read_header, this,
+ boost::asio::placeholders::error));
+ }
+ }
+
+ void handle_read_header(const boost::system::error_code& error)
+ {
+ if (!error && read_msg_.decode_header())
+ {
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
+ boost::bind(&chat_client::handle_read_body, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ do_close();
+ }
+ }
+
+ void handle_read_body(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout.write(read_msg_.body(), read_msg_.body_length());
+ std::cout << "\n";
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ boost::bind(&chat_client::handle_read_header, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ do_close();
+ }
+ }
+
+ void do_write(chat_message msg)
+ {
+ bool write_in_progress = !write_msgs_.empty();
+ write_msgs_.push_back(msg);
+ if (!write_in_progress)
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msgs_.front().data(),
+ write_msgs_.front().length()),
+ boost::bind(&chat_client::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ write_msgs_.pop_front();
+ if (!write_msgs_.empty())
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msgs_.front().data(),
+ write_msgs_.front().length()),
+ boost::bind(&chat_client::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ }
+ else
+ {
+ do_close();
+ }
+ }
+
+ void do_close()
+ {
+ socket_.close();
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ tcp::socket socket_;
+ chat_message read_msg_;
+ chat_message_queue write_msgs_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: chat_client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ tcp::resolver resolver(io_context);
+ tcp::resolver::results_type endpoints = resolver.resolve(argv[1], argv[2]);
+
+ chat_client c(io_context, endpoints);
+
+ boost::thread t(boost::bind(&boost::asio::io_context::run, &io_context));
+
+ char line[chat_message::max_body_length + 1];
+ while (std::cin.getline(line, chat_message::max_body_length + 1))
+ {
+ using namespace std; // For strlen and memcpy.
+ chat_message msg;
+ msg.body_length(strlen(line));
+ memcpy(msg.body(), line, msg.body_length());
+ msg.encode_header();
+ c.write(msg);
+ }
+
+ c.close();
+ t.join();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/chat/chat_message.hpp b/src/boost/libs/asio/example/cpp03/chat/chat_message.hpp
new file mode 100644
index 000000000..0c22c4b23
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/chat/chat_message.hpp
@@ -0,0 +1,93 @@
+//
+// chat_message.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 CHAT_MESSAGE_HPP
+#define CHAT_MESSAGE_HPP
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+class chat_message
+{
+public:
+ enum { header_length = 4 };
+ enum { max_body_length = 512 };
+
+ chat_message()
+ : body_length_(0)
+ {
+ }
+
+ const char* data() const
+ {
+ return data_;
+ }
+
+ char* data()
+ {
+ return data_;
+ }
+
+ size_t length() const
+ {
+ return header_length + body_length_;
+ }
+
+ const char* body() const
+ {
+ return data_ + header_length;
+ }
+
+ char* body()
+ {
+ return data_ + header_length;
+ }
+
+ size_t body_length() const
+ {
+ return body_length_;
+ }
+
+ void body_length(size_t new_length)
+ {
+ body_length_ = new_length;
+ if (body_length_ > max_body_length)
+ body_length_ = max_body_length;
+ }
+
+ bool decode_header()
+ {
+ using namespace std; // For strncat and atoi.
+ char header[header_length + 1] = "";
+ strncat(header, data_, header_length);
+ body_length_ = atoi(header);
+ if (body_length_ > max_body_length)
+ {
+ body_length_ = 0;
+ return false;
+ }
+ return true;
+ }
+
+ void encode_header()
+ {
+ using namespace std; // For sprintf and memcpy.
+ char header[header_length + 1] = "";
+ sprintf(header, "%4d", static_cast<int>(body_length_));
+ memcpy(data_, header, header_length);
+ }
+
+private:
+ char data_[header_length + max_body_length];
+ size_t body_length_;
+};
+
+#endif // CHAT_MESSAGE_HPP
diff --git a/src/boost/libs/asio/example/cpp03/chat/chat_server.cpp b/src/boost/libs/asio/example/cpp03/chat/chat_server.cpp
new file mode 100644
index 000000000..9347366fc
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/chat/chat_server.cpp
@@ -0,0 +1,249 @@
+//
+// chat_server.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <algorithm>
+#include <cstdlib>
+#include <deque>
+#include <iostream>
+#include <list>
+#include <set>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/asio.hpp>
+#include "chat_message.hpp"
+
+using boost::asio::ip::tcp;
+
+//----------------------------------------------------------------------
+
+typedef std::deque<chat_message> chat_message_queue;
+
+//----------------------------------------------------------------------
+
+class chat_participant
+{
+public:
+ virtual ~chat_participant() {}
+ virtual void deliver(const chat_message& msg) = 0;
+};
+
+typedef boost::shared_ptr<chat_participant> chat_participant_ptr;
+
+//----------------------------------------------------------------------
+
+class chat_room
+{
+public:
+ void join(chat_participant_ptr participant)
+ {
+ participants_.insert(participant);
+ std::for_each(recent_msgs_.begin(), recent_msgs_.end(),
+ boost::bind(&chat_participant::deliver,
+ participant, boost::placeholders::_1));
+ }
+
+ void leave(chat_participant_ptr participant)
+ {
+ participants_.erase(participant);
+ }
+
+ void deliver(const chat_message& msg)
+ {
+ recent_msgs_.push_back(msg);
+ while (recent_msgs_.size() > max_recent_msgs)
+ recent_msgs_.pop_front();
+
+ std::for_each(participants_.begin(), participants_.end(),
+ boost::bind(&chat_participant::deliver,
+ boost::placeholders::_1, boost::ref(msg)));
+ }
+
+private:
+ std::set<chat_participant_ptr> participants_;
+ enum { max_recent_msgs = 100 };
+ chat_message_queue recent_msgs_;
+};
+
+//----------------------------------------------------------------------
+
+class chat_session
+ : public chat_participant,
+ public boost::enable_shared_from_this<chat_session>
+{
+public:
+ chat_session(boost::asio::io_context& io_context, chat_room& room)
+ : socket_(io_context),
+ room_(room)
+ {
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ room_.join(shared_from_this());
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ boost::bind(
+ &chat_session::handle_read_header, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+
+ void deliver(const chat_message& msg)
+ {
+ bool write_in_progress = !write_msgs_.empty();
+ write_msgs_.push_back(msg);
+ if (!write_in_progress)
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msgs_.front().data(),
+ write_msgs_.front().length()),
+ boost::bind(&chat_session::handle_write, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ }
+
+ void handle_read_header(const boost::system::error_code& error)
+ {
+ if (!error && read_msg_.decode_header())
+ {
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
+ boost::bind(&chat_session::handle_read_body, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ room_.leave(shared_from_this());
+ }
+ }
+
+ void handle_read_body(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ room_.deliver(read_msg_);
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ boost::bind(&chat_session::handle_read_header, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ room_.leave(shared_from_this());
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ write_msgs_.pop_front();
+ if (!write_msgs_.empty())
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msgs_.front().data(),
+ write_msgs_.front().length()),
+ boost::bind(&chat_session::handle_write, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ }
+ else
+ {
+ room_.leave(shared_from_this());
+ }
+ }
+
+private:
+ tcp::socket socket_;
+ chat_room& room_;
+ chat_message read_msg_;
+ chat_message_queue write_msgs_;
+};
+
+typedef boost::shared_ptr<chat_session> chat_session_ptr;
+
+//----------------------------------------------------------------------
+
+class chat_server
+{
+public:
+ chat_server(boost::asio::io_context& io_context,
+ const tcp::endpoint& endpoint)
+ : io_context_(io_context),
+ acceptor_(io_context, endpoint)
+ {
+ start_accept();
+ }
+
+ void start_accept()
+ {
+ chat_session_ptr new_session(new chat_session(io_context_, room_));
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&chat_server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(chat_session_ptr session,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ session->start();
+ }
+
+ start_accept();
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ tcp::acceptor acceptor_;
+ chat_room room_;
+};
+
+typedef boost::shared_ptr<chat_server> chat_server_ptr;
+typedef std::list<chat_server_ptr> chat_server_list;
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc < 2)
+ {
+ std::cerr << "Usage: chat_server <port> [<port> ...]\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ chat_server_list servers;
+ for (int i = 1; i < argc; ++i)
+ {
+ using namespace std; // For atoi.
+ tcp::endpoint endpoint(tcp::v4(), atoi(argv[i]));
+ chat_server_ptr server(new chat_server(io_context, endpoint));
+ servers.push_back(server);
+ }
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/chat/posix_chat_client.cpp b/src/boost/libs/asio/example/cpp03/chat/posix_chat_client.cpp
new file mode 100644
index 000000000..85581ef6d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/chat/posix_chat_client.cpp
@@ -0,0 +1,204 @@
+//
+// posix_chat_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/asio.hpp>
+#include "chat_message.hpp"
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+
+using boost::asio::ip::tcp;
+namespace posix = boost::asio::posix;
+
+class posix_chat_client
+{
+public:
+ posix_chat_client(boost::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)
+ {
+ boost::asio::async_connect(socket_, endpoints,
+ boost::bind(&posix_chat_client::handle_connect, this,
+ boost::asio::placeholders::error));
+ }
+
+private:
+
+ void handle_connect(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ // Read the fixed-length header of the next message from the server.
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ boost::bind(&posix_chat_client::handle_read_header, this,
+ boost::asio::placeholders::error));
+
+ // Read a line of input entered by the user.
+ boost::asio::async_read_until(input_, input_buffer_, '\n',
+ boost::bind(&posix_chat_client::handle_read_input, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ }
+
+ void handle_read_header(const boost::system::error_code& error)
+ {
+ if (!error && read_msg_.decode_header())
+ {
+ // Read the variable-length body of the message from the server.
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
+ boost::bind(&posix_chat_client::handle_read_body, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void handle_read_body(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ // Write out the message we just received, terminated by a newline.
+ static char eol[] = { '\n' };
+ boost::array<boost::asio::const_buffer, 2> buffers = {{
+ boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
+ boost::asio::buffer(eol) }};
+ boost::asio::async_write(output_, buffers,
+ boost::bind(&posix_chat_client::handle_write_output, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void handle_write_output(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ // Read the fixed-length header of the next message from the server.
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ boost::bind(&posix_chat_client::handle_read_header, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void handle_read_input(const boost::system::error_code& error,
+ std::size_t length)
+ {
+ if (!error)
+ {
+ // 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();
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msg_.data(), write_msg_.length()),
+ boost::bind(&posix_chat_client::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ else if (error == boost::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();
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msg_.data(), write_msg_.length()),
+ boost::bind(&posix_chat_client::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ // Read a line of input entered by the user.
+ boost::asio::async_read_until(input_, input_buffer_, '\n',
+ boost::bind(&posix_chat_client::handle_read_input, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ 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_;
+ boost::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;
+ }
+
+ boost::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(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+int main() {}
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
diff --git a/src/boost/libs/asio/example/cpp03/echo/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/echo/Jamfile.v2
new file mode 100644
index 000000000..6111d428e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/echo/Jamfile.v2
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe async_tcp_echo_server : async_tcp_echo_server.cpp ;
+exe async_udp_echo_server : async_udp_echo_server.cpp ;
+exe blocking_tcp_echo_client : blocking_tcp_echo_client.cpp ;
+exe blocking_tcp_echo_server : blocking_tcp_echo_server.cpp ;
+exe blocking_udp_echo_client : blocking_udp_echo_client.cpp ;
+exe blocking_udp_echo_server : blocking_udp_echo_server.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/echo/async_tcp_echo_server.cpp b/src/boost/libs/asio/example/cpp03/echo/async_tcp_echo_server.cpp
new file mode 100644
index 000000000..55c1cb064
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/echo/async_tcp_echo_server.cpp
@@ -0,0 +1,137 @@
+//
+// async_tcp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/bind/bind.hpp>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+class session
+{
+public:
+ session(boost::asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ socket_.async_read_some(boost::asio::buffer(data_, max_length),
+ boost::bind(&session::handle_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+private:
+ void handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(data_, bytes_transferred),
+ boost::bind(&session::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ delete this;
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ socket_.async_read_some(boost::asio::buffer(data_, max_length),
+ boost::bind(&session::handle_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ delete this;
+ }
+ }
+
+ tcp::socket socket_;
+ enum { max_length = 1024 };
+ char data_[max_length];
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : io_context_(io_context),
+ acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
+ {
+ start_accept();
+ }
+
+private:
+ void start_accept()
+ {
+ session* new_session = new session(io_context_);
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(session* new_session,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_session->start();
+ }
+ else
+ {
+ delete new_session;
+ }
+
+ start_accept();
+ }
+
+ boost::asio::io_context& io_context_;
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: async_tcp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::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() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/echo/async_udp_echo_server.cpp b/src/boost/libs/asio/example/cpp03/echo/async_udp_echo_server.cpp
new file mode 100644
index 000000000..e7d91134e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/echo/async_udp_echo_server.cpp
@@ -0,0 +1,92 @@
+//
+// async_udp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/bind/bind.hpp>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::udp;
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : socket_(io_context, udp::endpoint(udp::v4(), port))
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(data_, max_length), sender_endpoint_,
+ boost::bind(&server::handle_receive_from, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+ void handle_receive_from(const boost::system::error_code& error,
+ size_t bytes_recvd)
+ {
+ if (!error && bytes_recvd > 0)
+ {
+ socket_.async_send_to(
+ boost::asio::buffer(data_, bytes_recvd), sender_endpoint_,
+ boost::bind(&server::handle_send_to, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(data_, max_length), sender_endpoint_,
+ boost::bind(&server::handle_receive_from, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ }
+
+ void handle_send_to(const boost::system::error_code& /*error*/,
+ size_t /*bytes_sent*/)
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(data_, max_length), sender_endpoint_,
+ boost::bind(&server::handle_receive_from, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+private:
+ udp::socket socket_;
+ udp::endpoint sender_endpoint_;
+ enum { max_length = 1024 };
+ char data_[max_length];
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: async_udp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::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() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/echo/blocking_tcp_echo_client.cpp b/src/boost/libs/asio/example/cpp03/echo/blocking_tcp_echo_client.cpp
new file mode 100644
index 000000000..f97d8daaa
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/echo/blocking_tcp_echo_client.cpp
@@ -0,0 +1,59 @@
+//
+// blocking_tcp_echo_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+enum { max_length = 1024 };
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ tcp::resolver resolver(io_context);
+ tcp::resolver::results_type endpoints =
+ resolver.resolve(tcp::v4(), argv[1], argv[2]);
+
+ tcp::socket s(io_context);
+ boost::asio::connect(s, endpoints);
+
+ using namespace std; // For strlen.
+ std::cout << "Enter message: ";
+ char request[max_length];
+ std::cin.getline(request, max_length);
+ size_t request_length = strlen(request);
+ boost::asio::write(s, boost::asio::buffer(request, request_length));
+
+ char reply[max_length];
+ size_t reply_length = boost::asio::read(s,
+ boost::asio::buffer(reply, request_length));
+ std::cout << "Reply is: ";
+ std::cout.write(reply, reply_length);
+ std::cout << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/echo/blocking_tcp_echo_server.cpp b/src/boost/libs/asio/example/cpp03/echo/blocking_tcp_echo_server.cpp
new file mode 100644
index 000000000..b5b364378
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/echo/blocking_tcp_echo_server.cpp
@@ -0,0 +1,80 @@
+//
+// blocking_tcp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/bind/bind.hpp>
+#include <boost/smart_ptr.hpp>
+#include <boost/asio.hpp>
+#include <boost/thread/thread.hpp>
+
+using boost::asio::ip::tcp;
+
+const int max_length = 1024;
+
+typedef boost::shared_ptr<tcp::socket> socket_ptr;
+
+void session(socket_ptr sock)
+{
+ try
+ {
+ for (;;)
+ {
+ char data[max_length];
+
+ boost::system::error_code error;
+ size_t length = sock->read_some(boost::asio::buffer(data), error);
+ if (error == boost::asio::error::eof)
+ break; // Connection closed cleanly by peer.
+ else if (error)
+ throw boost::system::system_error(error); // Some other error.
+
+ boost::asio::write(*sock, boost::asio::buffer(data, length));
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception in thread: " << e.what() << "\n";
+ }
+}
+
+void server(boost::asio::io_context& io_context, unsigned short port)
+{
+ tcp::acceptor a(io_context, tcp::endpoint(tcp::v4(), port));
+ for (;;)
+ {
+ socket_ptr sock(new tcp::socket(io_context));
+ a.accept(*sock);
+ boost::thread t(boost::bind(session, sock));
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: blocking_tcp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ using namespace std; // For atoi.
+ server(io_context, atoi(argv[1]));
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/echo/blocking_udp_echo_client.cpp b/src/boost/libs/asio/example/cpp03/echo/blocking_udp_echo_client.cpp
new file mode 100644
index 000000000..89afd03bc
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/echo/blocking_udp_echo_client.cpp
@@ -0,0 +1,59 @@
+//
+// blocking_udp_echo_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::udp;
+
+enum { max_length = 1024 };
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: blocking_udp_echo_client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ udp::socket s(io_context, udp::endpoint(udp::v4(), 0));
+
+ udp::resolver resolver(io_context);
+ udp::resolver::results_type endpoints =
+ resolver.resolve(udp::v4(), argv[1], argv[2]);
+
+ using namespace std; // For strlen.
+ std::cout << "Enter message: ";
+ char request[max_length];
+ std::cin.getline(request, max_length);
+ size_t request_length = strlen(request);
+ s.send_to(boost::asio::buffer(request, request_length), *endpoints.begin());
+
+ char reply[max_length];
+ udp::endpoint sender_endpoint;
+ size_t reply_length = s.receive_from(
+ boost::asio::buffer(reply, max_length), sender_endpoint);
+ std::cout << "Reply is: ";
+ std::cout.write(reply, reply_length);
+ std::cout << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/echo/blocking_udp_echo_server.cpp b/src/boost/libs/asio/example/cpp03/echo/blocking_udp_echo_server.cpp
new file mode 100644
index 000000000..0db7cd0e1
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/echo/blocking_udp_echo_server.cpp
@@ -0,0 +1,53 @@
+//
+// blocking_udp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::udp;
+
+enum { max_length = 1024 };
+
+void server(boost::asio::io_context& io_context, unsigned short port)
+{
+ udp::socket sock(io_context, udp::endpoint(udp::v4(), port));
+ for (;;)
+ {
+ char data[max_length];
+ udp::endpoint sender_endpoint;
+ size_t length = sock.receive_from(
+ boost::asio::buffer(data, max_length), sender_endpoint);
+ sock.send_to(boost::asio::buffer(data, length), sender_endpoint);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: blocking_udp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ using namespace std; // For atoi.
+ server(io_context, atoi(argv[1]));
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/fork/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/fork/Jamfile.v2
new file mode 100644
index 000000000..1d93fe89e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/fork/Jamfile.v2
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe daemon
+ : daemon.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe process_per_connection
+ : process_per_connection.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/fork/daemon.cpp b/src/boost/libs/asio/example/cpp03/fork/daemon.cpp
new file mode 100644
index 000000000..c69d3a805
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/fork/daemon.cpp
@@ -0,0 +1,190 @@
+//
+// daemon.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+#include <ctime>
+#include <iostream>
+#include <syslog.h>
+#include <unistd.h>
+
+using boost::asio::ip::udp;
+
+class udp_daytime_server
+{
+public:
+ udp_daytime_server(boost::asio::io_context& io_context)
+ : socket_(io_context, udp::endpoint(udp::v4(), 13))
+ {
+ start_receive();
+ }
+
+private:
+ void start_receive()
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(recv_buffer_), remote_endpoint_,
+ boost::bind(&udp_daytime_server::handle_receive,
+ this, boost::placeholders::_1));
+ }
+
+ void handle_receive(const boost::system::error_code& ec)
+ {
+ if (!ec)
+ {
+ using namespace std; // For time_t, time and ctime;
+ time_t now = time(0);
+ std::string message = ctime(&now);
+
+ boost::system::error_code ignored_ec;
+ socket_.send_to(boost::asio::buffer(message),
+ remote_endpoint_, 0, ignored_ec);
+ }
+
+ start_receive();
+ }
+
+ udp::socket socket_;
+ udp::endpoint remote_endpoint_;
+ boost::array<char, 1> recv_buffer_;
+};
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context;
+
+ // Initialise the server before becoming a daemon. If the process is
+ // started from a shell, this means any errors will be reported back to the
+ // user.
+ udp_daytime_server server(io_context);
+
+ // Register signal handlers so that the daemon may be shut down. You may
+ // also want to register for other signals, such as SIGHUP to trigger a
+ // re-read of a configuration file.
+ boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
+ signals.async_wait(
+ boost::bind(&boost::asio::io_context::stop, &io_context));
+
+ // Inform the io_context that we are about to become a daemon. The
+ // io_context cleans up any internal resources, such as threads, that may
+ // interfere with forking.
+ io_context.notify_fork(boost::asio::io_context::fork_prepare);
+
+ // Fork the process and have the parent exit. If the process was started
+ // from a shell, this returns control to the user. Forking a new process is
+ // also a prerequisite for the subsequent call to setsid().
+ if (pid_t pid = fork())
+ {
+ if (pid > 0)
+ {
+ // We're in the parent process and need to exit.
+ //
+ // When the exit() function is used, the program terminates without
+ // invoking local variables' destructors. Only global variables are
+ // destroyed. As the io_context object is a local variable, this means
+ // we do not have to call:
+ //
+ // io_context.notify_fork(boost::asio::io_context::fork_parent);
+ //
+ // However, this line should be added before each call to exit() if
+ // using a global io_context object. An additional call:
+ //
+ // io_context.notify_fork(boost::asio::io_context::fork_prepare);
+ //
+ // should also precede the second fork().
+ exit(0);
+ }
+ else
+ {
+ syslog(LOG_ERR | LOG_USER, "First fork failed: %m");
+ return 1;
+ }
+ }
+
+ // Make the process a new session leader. This detaches it from the
+ // terminal.
+ setsid();
+
+ // A process inherits its working directory from its parent. This could be
+ // on a mounted filesystem, which means that the running daemon would
+ // prevent this filesystem from being unmounted. Changing to the root
+ // directory avoids this problem.
+ chdir("/");
+
+ // The file mode creation mask is also inherited from the parent process.
+ // We don't want to restrict the permissions on files created by the
+ // daemon, so the mask is cleared.
+ umask(0);
+
+ // A second fork ensures the process cannot acquire a controlling terminal.
+ if (pid_t pid = fork())
+ {
+ if (pid > 0)
+ {
+ exit(0);
+ }
+ else
+ {
+ syslog(LOG_ERR | LOG_USER, "Second fork failed: %m");
+ return 1;
+ }
+ }
+
+ // Close the standard streams. This decouples the daemon from the terminal
+ // that started it.
+ close(0);
+ close(1);
+ close(2);
+
+ // We don't want the daemon to have any standard input.
+ if (open("/dev/null", O_RDONLY) < 0)
+ {
+ syslog(LOG_ERR | LOG_USER, "Unable to open /dev/null: %m");
+ return 1;
+ }
+
+ // Send standard output to a log file.
+ const char* output = "/tmp/asio.daemon.out";
+ const int flags = O_WRONLY | O_CREAT | O_APPEND;
+ const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ if (open(output, flags, mode) < 0)
+ {
+ syslog(LOG_ERR | LOG_USER, "Unable to open output file %s: %m", output);
+ return 1;
+ }
+
+ // Also send standard error to the same log file.
+ if (dup(1) < 0)
+ {
+ syslog(LOG_ERR | LOG_USER, "Unable to dup output descriptor: %m");
+ return 1;
+ }
+
+ // Inform the io_context that we have finished becoming a daemon. The
+ // io_context uses this opportunity to create any internal file descriptors
+ // that need to be private to the new process.
+ io_context.notify_fork(boost::asio::io_context::fork_child);
+
+ // The io_context can now be used normally.
+ syslog(LOG_INFO | LOG_USER, "Daemon started");
+ io_context.run();
+ syslog(LOG_INFO | LOG_USER, "Daemon stopped");
+ }
+ catch (std::exception& e)
+ {
+ syslog(LOG_ERR | LOG_USER, "Exception: %s", e.what());
+ std::cerr << "Exception: " << e.what() << std::endl;
+ }
+}
diff --git a/src/boost/libs/asio/example/cpp03/fork/process_per_connection.cpp b/src/boost/libs/asio/example/cpp03/fork/process_per_connection.cpp
new file mode 100644
index 000000000..f7f947222
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/fork/process_per_connection.cpp
@@ -0,0 +1,161 @@
+//
+// process_per_connection.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+using boost::asio::ip::tcp;
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, unsigned short port)
+ : io_context_(io_context),
+ signal_(io_context, SIGCHLD),
+ acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
+ socket_(io_context)
+ {
+ start_signal_wait();
+ start_accept();
+ }
+
+private:
+ void start_signal_wait()
+ {
+ signal_.async_wait(boost::bind(&server::handle_signal_wait, this));
+ }
+
+ void handle_signal_wait()
+ {
+ // Only the parent process should check for this signal. We can determine
+ // whether we are in the parent by checking if the acceptor is still open.
+ if (acceptor_.is_open())
+ {
+ // Reap completed child processes so that we don't end up with zombies.
+ int status = 0;
+ while (waitpid(-1, &status, WNOHANG) > 0) {}
+
+ start_signal_wait();
+ }
+ }
+
+ void start_accept()
+ {
+ acceptor_.async_accept(socket_,
+ boost::bind(&server::handle_accept, this, boost::placeholders::_1));
+ }
+
+ void handle_accept(const boost::system::error_code& ec)
+ {
+ if (!ec)
+ {
+ // Inform the io_context that we are about to fork. The io_context cleans
+ // up any internal resources, such as threads, that may interfere with
+ // forking.
+ io_context_.notify_fork(boost::asio::io_context::fork_prepare);
+
+ if (fork() == 0)
+ {
+ // Inform the io_context that the fork is finished and that this is the
+ // child process. The io_context uses this opportunity to create any
+ // internal file descriptors that must be private to the new process.
+ io_context_.notify_fork(boost::asio::io_context::fork_child);
+
+ // The child won't be accepting new connections, so we can close the
+ // acceptor. It remains open in the parent.
+ acceptor_.close();
+
+ // The child process is not interested in processing the SIGCHLD signal.
+ signal_.cancel();
+
+ start_read();
+ }
+ else
+ {
+ // Inform the io_context that the fork is finished (or failed) and that
+ // this is the parent process. The io_context uses this opportunity to
+ // recreate any internal resources that were cleaned up during
+ // preparation for the fork.
+ io_context_.notify_fork(boost::asio::io_context::fork_parent);
+
+ socket_.close();
+ start_accept();
+ }
+ }
+ else
+ {
+ std::cerr << "Accept error: " << ec.message() << std::endl;
+ start_accept();
+ }
+ }
+
+ void start_read()
+ {
+ socket_.async_read_some(boost::asio::buffer(data_),
+ boost::bind(&server::handle_read, this,
+ boost::placeholders::_1, boost::placeholders::_2));
+ }
+
+ void handle_read(const boost::system::error_code& ec, std::size_t length)
+ {
+ if (!ec)
+ start_write(length);
+ }
+
+ void start_write(std::size_t length)
+ {
+ boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
+ boost::bind(&server::handle_write, this, boost::placeholders::_1));
+ }
+
+ void handle_write(const boost::system::error_code& ec)
+ {
+ if (!ec)
+ start_read();
+ }
+
+ boost::asio::io_context& io_context_;
+ boost::asio::signal_set signal_;
+ tcp::acceptor acceptor_;
+ tcp::socket socket_;
+ boost::array<char, 1024> data_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: process_per_connection <port>\n";
+ return 1;
+ }
+
+ boost::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;
+ }
+}
diff --git a/src/boost/libs/asio/example/cpp03/http/client/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/http/client/Jamfile.v2
new file mode 100644
index 000000000..eedb4068f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/client/Jamfile.v2
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe async_client : async_client.cpp ;
+exe sync_client : sync_client.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/http/client/async_client.cpp b/src/boost/libs/asio/example/cpp03/http/client/async_client.cpp
new file mode 100644
index 000000000..e9bf6baf5
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/client/async_client.cpp
@@ -0,0 +1,204 @@
+//
+// async_client.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+
+using boost::asio::ip::tcp;
+
+class client
+{
+public:
+ client(boost::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",
+ boost::bind(&client::handle_resolve, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::results));
+ }
+
+private:
+ void handle_resolve(const boost::system::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.
+ boost::asio::async_connect(socket_, endpoints,
+ boost::bind(&client::handle_connect, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ std::cout << "Error: " << err.message() << "\n";
+ }
+ }
+
+ void handle_connect(const boost::system::error_code& err)
+ {
+ if (!err)
+ {
+ // The connection was successful. Send the request.
+ boost::asio::async_write(socket_, request_,
+ boost::bind(&client::handle_write_request, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ std::cout << "Error: " << err.message() << "\n";
+ }
+ }
+
+ void handle_write_request(const boost::system::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.
+ boost::asio::async_read_until(socket_, response_, "\r\n",
+ boost::bind(&client::handle_read_status_line, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ std::cout << "Error: " << err.message() << "\n";
+ }
+ }
+
+ void handle_read_status_line(const boost::system::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.
+ boost::asio::async_read_until(socket_, response_, "\r\n\r\n",
+ boost::bind(&client::handle_read_headers, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ std::cout << "Error: " << err << "\n";
+ }
+ }
+
+ void handle_read_headers(const boost::system::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.
+ boost::asio::async_read(socket_, response_,
+ boost::asio::transfer_at_least(1),
+ boost::bind(&client::handle_read_content, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ std::cout << "Error: " << err << "\n";
+ }
+ }
+
+ void handle_read_content(const boost::system::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.
+ boost::asio::async_read(socket_, response_,
+ boost::asio::transfer_at_least(1),
+ boost::bind(&client::handle_read_content, this,
+ boost::asio::placeholders::error));
+ }
+ else if (err != boost::asio::error::eof)
+ {
+ std::cout << "Error: " << err << "\n";
+ }
+ }
+
+ tcp::resolver resolver_;
+ tcp::socket socket_;
+ boost::asio::streambuf request_;
+ boost::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;
+ }
+
+ boost::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/src/boost/libs/asio/example/cpp03/http/client/sync_client.cpp b/src/boost/libs/asio/example/cpp03/http/client/sync_client.cpp
new file mode 100644
index 000000000..a3b6a5c61
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/client/sync_client.cpp
@@ -0,0 +1,106 @@
+//
+// sync_client.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+
+using boost::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;
+ }
+
+ boost::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);
+ boost::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.
+ boost::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.
+ boost::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.
+ boost::asio::streambuf response;
+ boost::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.
+ boost::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.
+ boost::system::error_code error;
+ while (boost::asio::read(socket, response,
+ boost::asio::transfer_at_least(1), error))
+ std::cout << &response;
+ if (error != boost::asio::error::eof)
+ throw boost::system::system_error(error);
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/http/doc_root/data_1K.html b/src/boost/libs/asio/example/cpp03/http/doc_root/data_1K.html
new file mode 100644
index 000000000..80e07f009
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/doc_root/data_1K.html
@@ -0,0 +1,28 @@
+<!--
+Copyright (c) 2003-2020 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)
+-->
+
+<html>
+<body>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the<br/>
+</body>
+</html>
+
+<!-- boostinspect:nounlinked -->
diff --git a/src/boost/libs/asio/example/cpp03/http/doc_root/data_2K.html b/src/boost/libs/asio/example/cpp03/http/doc_root/data_2K.html
new file mode 100644
index 000000000..0584cbe48
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/doc_root/data_2K.html
@@ -0,0 +1,49 @@
+<!--
+Copyright (c) 2003-2020 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)
+-->
+
+<html>
+<body>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps ove<br/>
+</body>
+</html>
+
+<!-- boostinspect:nounlinked -->
diff --git a/src/boost/libs/asio/example/cpp03/http/doc_root/data_4K.html b/src/boost/libs/asio/example/cpp03/http/doc_root/data_4K.html
new file mode 100644
index 000000000..4c35214d3
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/doc_root/data_4K.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2003-2020 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)
+-->
+
+<html>
+<body>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox<br/>
+</body>
+</html>
+
+<!-- boostinspect:nounlinked -->
diff --git a/src/boost/libs/asio/example/cpp03/http/doc_root/data_8K.html b/src/boost/libs/asio/example/cpp03/http/doc_root/data_8K.html
new file mode 100644
index 000000000..fb5624902
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/doc_root/data_8K.html
@@ -0,0 +1,175 @@
+<!--
+Copyright (c) 2003-2020 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)
+-->
+
+<html>
+<body>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+The quick brown fox jumps over the lazy dog<br/>
+....
+</body>
+</html>
+
+<!-- boostinspect:nounlinked -->
diff --git a/src/boost/libs/asio/example/cpp03/http/server/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/http/server/Jamfile.v2
new file mode 100644
index 000000000..ed1e3e8ee
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/Jamfile.v2
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : connection.cpp
+ connection_manager.cpp
+ main.cpp
+ mime_types.cpp
+ reply.cpp
+ request_handler.cpp
+ request_parser.cpp
+ server.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ /boost/thread//boost_thread
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/http/server/connection.cpp b/src/boost/libs/asio/example/cpp03/http/server/connection.cpp
new file mode 100644
index 000000000..9bc9a0780
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/connection.cpp
@@ -0,0 +1,99 @@
+//
+// connection.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <vector>
+#include <boost/bind/bind.hpp>
+#include "connection_manager.hpp"
+#include "request_handler.hpp"
+
+namespace http {
+namespace server {
+
+connection::connection(boost::asio::io_context& io_context,
+ connection_manager& manager, request_handler& handler)
+ : socket_(io_context),
+ connection_manager_(manager),
+ request_handler_(handler)
+{
+}
+
+boost::asio::ip::tcp::socket& connection::socket()
+{
+ return socket_;
+}
+
+void connection::start()
+{
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ boost::bind(&connection::handle_read, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+}
+
+void connection::stop()
+{
+ socket_.close();
+}
+
+void connection::handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred)
+{
+ if (!e)
+ {
+ boost::tribool result;
+ boost::tie(result, boost::tuples::ignore) = request_parser_.parse(
+ request_, buffer_.data(), buffer_.data() + bytes_transferred);
+
+ if (result)
+ {
+ request_handler_.handle_request(request_, reply_);
+ boost::asio::async_write(socket_, reply_.to_buffers(),
+ boost::bind(&connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ else if (!result)
+ {
+ reply_ = reply::stock_reply(reply::bad_request);
+ boost::asio::async_write(socket_, reply_.to_buffers(),
+ boost::bind(&connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ boost::bind(&connection::handle_read, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ }
+ else if (e != boost::asio::error::operation_aborted)
+ {
+ connection_manager_.stop(shared_from_this());
+ }
+}
+
+void connection::handle_write(const boost::system::error_code& e)
+{
+ if (!e)
+ {
+ // Initiate graceful connection closure.
+ boost::system::error_code ignored_ec;
+ socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
+ }
+
+ if (e != boost::asio::error::operation_aborted)
+ {
+ connection_manager_.stop(shared_from_this());
+ }
+}
+
+} // namespace server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server/connection.hpp b/src/boost/libs/asio/example/cpp03/http/server/connection.hpp
new file mode 100644
index 000000000..a701bc68f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/connection.hpp
@@ -0,0 +1,83 @@
+//
+// connection.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_CONNECTION_HPP
+#define HTTP_CONNECTION_HPP
+
+#include <boost/asio.hpp>
+#include <boost/array.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include "reply.hpp"
+#include "request.hpp"
+#include "request_handler.hpp"
+#include "request_parser.hpp"
+
+namespace http {
+namespace server {
+
+class connection_manager;
+
+/// Represents a single connection from a client.
+class connection
+ : public boost::enable_shared_from_this<connection>,
+ private boost::noncopyable
+{
+public:
+ /// Construct a connection with the given io_context.
+ explicit connection(boost::asio::io_context& io_context,
+ connection_manager& manager, request_handler& handler);
+
+ /// Get the socket associated with the connection.
+ boost::asio::ip::tcp::socket& socket();
+
+ /// Start the first asynchronous operation for the connection.
+ void start();
+
+ /// Stop all asynchronous operations associated with the connection.
+ void stop();
+
+private:
+ /// Handle completion of a read operation.
+ void handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred);
+
+ /// Handle completion of a write operation.
+ void handle_write(const boost::system::error_code& e);
+
+ /// Socket for the connection.
+ boost::asio::ip::tcp::socket socket_;
+
+ /// The manager for this connection.
+ connection_manager& connection_manager_;
+
+ /// The handler used to process the incoming request.
+ request_handler& request_handler_;
+
+ /// Buffer for incoming data.
+ boost::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 boost::shared_ptr<connection> connection_ptr;
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_CONNECTION_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server/connection_manager.cpp b/src/boost/libs/asio/example/cpp03/http/server/connection_manager.cpp
new file mode 100644
index 000000000..57a509d26
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/connection_manager.cpp
@@ -0,0 +1,38 @@
+//
+// connection_manager.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_manager.hpp"
+#include <algorithm>
+#include <boost/bind/bind.hpp>
+
+namespace http {
+namespace server {
+
+void connection_manager::start(connection_ptr c)
+{
+ connections_.insert(c);
+ c->start();
+}
+
+void connection_manager::stop(connection_ptr c)
+{
+ connections_.erase(c);
+ c->stop();
+}
+
+void connection_manager::stop_all()
+{
+ std::for_each(connections_.begin(), connections_.end(),
+ boost::bind(&connection::stop, boost::placeholders::_1));
+ connections_.clear();
+}
+
+} // namespace server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server/connection_manager.hpp b/src/boost/libs/asio/example/cpp03/http/server/connection_manager.hpp
new file mode 100644
index 000000000..48c90711f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/connection_manager.hpp
@@ -0,0 +1,44 @@
+//
+// connection_manager.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_CONNECTION_MANAGER_HPP
+#define HTTP_CONNECTION_MANAGER_HPP
+
+#include <set>
+#include <boost/noncopyable.hpp>
+#include "connection.hpp"
+
+namespace http {
+namespace server {
+
+/// Manages open connections so that they may be cleanly stopped when the server
+/// needs to shut down.
+class connection_manager
+ : private boost::noncopyable
+{
+public:
+ /// Add the specified connection to the manager and start it.
+ void start(connection_ptr c);
+
+ /// Stop the specified connection.
+ void stop(connection_ptr c);
+
+ /// Stop all connections.
+ void stop_all();
+
+private:
+ /// The managed connections.
+ std::set<connection_ptr> connections_;
+};
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_CONNECTION_MANAGER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server/header.hpp b/src/boost/libs/asio/example/cpp03/http/server/header.hpp
new file mode 100644
index 000000000..7e176c3b0
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/header.hpp
@@ -0,0 +1,28 @@
+//
+// header.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_HEADER_HPP
+#define HTTP_HEADER_HPP
+
+#include <string>
+
+namespace http {
+namespace server {
+
+struct header
+{
+ std::string name;
+ std::string value;
+};
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_HEADER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server/main.cpp b/src/boost/libs/asio/example/cpp03/http/server/main.cpp
new file mode 100644
index 000000000..a073a7d4d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/main.cpp
@@ -0,0 +1,44 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include "server.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;
+ }
+
+ // Initialise the server.
+ http::server::server s(argv[1], argv[2], argv[3]);
+
+ // Run the server until stopped.
+ s.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/http/server/mime_types.cpp b/src/boost/libs/asio/example/cpp03/http/server/mime_types.cpp
new file mode 100644
index 000000000..3964af74c
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/mime_types.cpp
@@ -0,0 +1,46 @@
+//
+// mime_types.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 server {
+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 server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server/mime_types.hpp b/src/boost/libs/asio/example/cpp03/http/server/mime_types.hpp
new file mode 100644
index 000000000..e9bb88268
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/mime_types.hpp
@@ -0,0 +1,27 @@
+//
+// mime_types.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_MIME_TYPES_HPP
+#define HTTP_MIME_TYPES_HPP
+
+#include <string>
+
+namespace http {
+namespace server {
+namespace mime_types {
+
+/// Convert a file extension into a MIME type.
+std::string extension_to_type(const std::string& extension);
+
+} // namespace mime_types
+} // namespace server
+} // namespace http
+
+#endif // HTTP_MIME_TYPES_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server/reply.cpp b/src/boost/libs/asio/example/cpp03/http/server/reply.cpp
new file mode 100644
index 000000000..59eef1cb5
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/reply.cpp
@@ -0,0 +1,256 @@
+//
+// reply.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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>
+#include <boost/lexical_cast.hpp>
+
+namespace http {
+namespace server {
+
+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";
+
+boost::asio::const_buffer to_buffer(reply::status_type status)
+{
+ switch (status)
+ {
+ case reply::ok:
+ return boost::asio::buffer(ok);
+ case reply::created:
+ return boost::asio::buffer(created);
+ case reply::accepted:
+ return boost::asio::buffer(accepted);
+ case reply::no_content:
+ return boost::asio::buffer(no_content);
+ case reply::multiple_choices:
+ return boost::asio::buffer(multiple_choices);
+ case reply::moved_permanently:
+ return boost::asio::buffer(moved_permanently);
+ case reply::moved_temporarily:
+ return boost::asio::buffer(moved_temporarily);
+ case reply::not_modified:
+ return boost::asio::buffer(not_modified);
+ case reply::bad_request:
+ return boost::asio::buffer(bad_request);
+ case reply::unauthorized:
+ return boost::asio::buffer(unauthorized);
+ case reply::forbidden:
+ return boost::asio::buffer(forbidden);
+ case reply::not_found:
+ return boost::asio::buffer(not_found);
+ case reply::internal_server_error:
+ return boost::asio::buffer(internal_server_error);
+ case reply::not_implemented:
+ return boost::asio::buffer(not_implemented);
+ case reply::bad_gateway:
+ return boost::asio::buffer(bad_gateway);
+ case reply::service_unavailable:
+ return boost::asio::buffer(service_unavailable);
+ default:
+ return boost::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<boost::asio::const_buffer> reply::to_buffers()
+{
+ std::vector<boost::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(boost::asio::buffer(h.name));
+ buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator));
+ buffers.push_back(boost::asio::buffer(h.value));
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ }
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ buffers.push_back(boost::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 = boost::lexical_cast<std::string>(rep.content.size());
+ rep.headers[1].name = "Content-Type";
+ rep.headers[1].value = "text/html";
+ return rep;
+}
+
+} // namespace server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server/reply.hpp b/src/boost/libs/asio/example/cpp03/http/server/reply.hpp
new file mode 100644
index 000000000..6a3240e2d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/reply.hpp
@@ -0,0 +1,64 @@
+//
+// reply.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_REPLY_HPP
+#define HTTP_REPLY_HPP
+
+#include <string>
+#include <vector>
+#include <boost/asio.hpp>
+#include "header.hpp"
+
+namespace http {
+namespace server {
+
+/// 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<boost::asio::const_buffer> to_buffers();
+
+ /// Get a stock reply.
+ static reply stock_reply(status_type status);
+};
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_REPLY_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server/request.hpp b/src/boost/libs/asio/example/cpp03/http/server/request.hpp
new file mode 100644
index 000000000..358133512
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/request.hpp
@@ -0,0 +1,34 @@
+//
+// request.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_REQUEST_HPP
+#define HTTP_REQUEST_HPP
+
+#include <string>
+#include <vector>
+#include "header.hpp"
+
+namespace http {
+namespace server {
+
+/// 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 server
+} // namespace http
+
+#endif // HTTP_REQUEST_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server/request_handler.cpp b/src/boost/libs/asio/example/cpp03/http/server/request_handler.cpp
new file mode 100644
index 000000000..2e38447b3
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/request_handler.cpp
@@ -0,0 +1,122 @@
+//
+// request_handler.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/lexical_cast.hpp>
+#include "mime_types.hpp"
+#include "reply.hpp"
+#include "request.hpp"
+
+namespace http {
+namespace server {
+
+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 = boost::lexical_cast<std::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 server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server/request_handler.hpp b/src/boost/libs/asio/example/cpp03/http/server/request_handler.hpp
new file mode 100644
index 000000000..2f542a1e4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/request_handler.hpp
@@ -0,0 +1,46 @@
+//
+// request_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_REQUEST_HANDLER_HPP
+#define HTTP_REQUEST_HANDLER_HPP
+
+#include <string>
+#include <boost/noncopyable.hpp>
+
+namespace http {
+namespace server {
+
+struct reply;
+struct request;
+
+/// The common handler for all incoming requests.
+class request_handler
+ : private boost::noncopyable
+{
+public:
+ /// 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 server
+} // namespace http
+
+#endif // HTTP_REQUEST_HANDLER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server/request_parser.cpp b/src/boost/libs/asio/example/cpp03/http/server/request_parser.cpp
new file mode 100644
index 000000000..acfdf311b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/request_parser.cpp
@@ -0,0 +1,315 @@
+//
+// request_parser.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 server {
+
+request_parser::request_parser()
+ : state_(method_start)
+{
+}
+
+void request_parser::reset()
+{
+ state_ = method_start;
+}
+
+boost::tribool request_parser::consume(request& req, char input)
+{
+ switch (state_)
+ {
+ case method_start:
+ if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ state_ = method;
+ req.method.push_back(input);
+ return boost::indeterminate;
+ }
+ case method:
+ if (input == ' ')
+ {
+ state_ = uri;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.method.push_back(input);
+ return boost::indeterminate;
+ }
+ case uri:
+ if (input == ' ')
+ {
+ state_ = http_version_h;
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.uri.push_back(input);
+ return boost::indeterminate;
+ }
+ case http_version_h:
+ if (input == 'H')
+ {
+ state_ = http_version_t_1;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_t_1:
+ if (input == 'T')
+ {
+ state_ = http_version_t_2;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_t_2:
+ if (input == 'T')
+ {
+ state_ = http_version_p;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_p:
+ if (input == 'P')
+ {
+ state_ = http_version_slash;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_slash:
+ if (input == '/')
+ {
+ req.http_version_major = 0;
+ req.http_version_minor = 0;
+ state_ = http_version_major_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ 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 boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_major:
+ if (input == '.')
+ {
+ state_ = http_version_minor_start;
+ return boost::indeterminate;
+ }
+ else if (is_digit(input))
+ {
+ req.http_version_major = req.http_version_major * 10 + input - '0';
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ 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 boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_minor:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_1;
+ return boost::indeterminate;
+ }
+ else if (is_digit(input))
+ {
+ req.http_version_minor = req.http_version_minor * 10 + input - '0';
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case expecting_newline_1:
+ if (input == '\n')
+ {
+ state_ = header_line_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case header_line_start:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_3;
+ return boost::indeterminate;
+ }
+ else if (!req.headers.empty() && (input == ' ' || input == '\t'))
+ {
+ state_ = header_lws;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.push_back(header());
+ req.headers.back().name.push_back(input);
+ state_ = header_name;
+ return boost::indeterminate;
+ }
+ case header_lws:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_2;
+ return boost::indeterminate;
+ }
+ else if (input == ' ' || input == '\t')
+ {
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ state_ = header_value;
+ req.headers.back().value.push_back(input);
+ return boost::indeterminate;
+ }
+ case header_name:
+ if (input == ':')
+ {
+ state_ = space_before_header_value;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.back().name.push_back(input);
+ return boost::indeterminate;
+ }
+ case space_before_header_value:
+ if (input == ' ')
+ {
+ state_ = header_value;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case header_value:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_2;
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.back().value.push_back(input);
+ return boost::indeterminate;
+ }
+ case expecting_newline_2:
+ if (input == '\n')
+ {
+ state_ = header_line_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case expecting_newline_3:
+ return (input == '\n');
+ default:
+ return false;
+ }
+}
+
+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 server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server/request_parser.hpp b/src/boost/libs/asio/example/cpp03/http/server/request_parser.hpp
new file mode 100644
index 000000000..e13a13181
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/request_parser.hpp
@@ -0,0 +1,95 @@
+//
+// request_parser.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_REQUEST_PARSER_HPP
+#define HTTP_REQUEST_PARSER_HPP
+
+#include <boost/logic/tribool.hpp>
+#include <boost/tuple/tuple.hpp>
+
+namespace http {
+namespace server {
+
+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();
+
+ /// Parse some data. The tribool return value is true when a complete request
+ /// has been parsed, false 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>
+ boost::tuple<boost::tribool, InputIterator> parse(request& req,
+ InputIterator begin, InputIterator end)
+ {
+ while (begin != end)
+ {
+ boost::tribool result = consume(req, *begin++);
+ if (result || !result)
+ return boost::make_tuple(result, begin);
+ }
+ boost::tribool result = boost::indeterminate;
+ return boost::make_tuple(result, begin);
+ }
+
+private:
+ /// Handle the next character of input.
+ boost::tribool 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 server
+} // namespace http
+
+#endif // HTTP_REQUEST_PARSER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server/server.cpp b/src/boost/libs/asio/example/cpp03/http/server/server.cpp
new file mode 100644
index 000000000..42253d878
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/server.cpp
@@ -0,0 +1,94 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/bind/bind.hpp>
+#include <signal.h>
+
+namespace http {
+namespace server {
+
+server::server(const std::string& address, const std::string& port,
+ const std::string& doc_root)
+ : io_context_(),
+ signals_(io_context_),
+ acceptor_(io_context_),
+ connection_manager_(),
+ new_connection_(),
+ 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)
+ signals_.async_wait(boost::bind(&server::handle_stop, this));
+
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+ boost::asio::ip::tcp::resolver resolver(io_context_);
+ boost::asio::ip::tcp::endpoint endpoint =
+ *resolver.resolve(address, port).begin();
+ acceptor_.open(endpoint.protocol());
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor_.bind(endpoint);
+ acceptor_.listen();
+
+ start_accept();
+}
+
+void server::run()
+{
+ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the server is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+ io_context_.run();
+}
+
+void server::start_accept()
+{
+ new_connection_.reset(new connection(io_context_,
+ connection_manager_, request_handler_));
+ acceptor_.async_accept(new_connection_->socket(),
+ boost::bind(&server::handle_accept, this,
+ boost::asio::placeholders::error));
+}
+
+void server::handle_accept(const boost::system::error_code& e)
+{
+ // Check whether the server was stopped by a signal before this completion
+ // handler had a chance to run.
+ if (!acceptor_.is_open())
+ {
+ return;
+ }
+
+ if (!e)
+ {
+ connection_manager_.start(new_connection_);
+ }
+
+ start_accept();
+}
+
+void server::handle_stop()
+{
+ // The server is stopped by cancelling all outstanding asynchronous
+ // operations. Once all operations have finished the io_context::run() call
+ // will exit.
+ acceptor_.close();
+ connection_manager_.stop_all();
+}
+
+} // namespace server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server/server.hpp b/src/boost/libs/asio/example/cpp03/http/server/server.hpp
new file mode 100644
index 000000000..e91b3d5fd
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server/server.hpp
@@ -0,0 +1,69 @@
+//
+// server.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_SERVER_HPP
+#define HTTP_SERVER_HPP
+
+#include <boost/asio.hpp>
+#include <string>
+#include <boost/noncopyable.hpp>
+#include "connection.hpp"
+#include "connection_manager.hpp"
+#include "request_handler.hpp"
+
+namespace http {
+namespace server {
+
+/// The top-level class of the HTTP server.
+class server
+ : private boost::noncopyable
+{
+public:
+ /// 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);
+
+ /// Run the server's io_context loop.
+ void run();
+
+private:
+ /// Initiate an asynchronous accept operation.
+ void start_accept();
+
+ /// Handle completion of an asynchronous accept operation.
+ void handle_accept(const boost::system::error_code& e);
+
+ /// Handle a request to stop the server.
+ void handle_stop();
+
+ /// The io_context used to perform asynchronous operations.
+ boost::asio::io_context io_context_;
+
+ /// The signal_set is used to register for process termination notifications.
+ boost::asio::signal_set signals_;
+
+ /// Acceptor used to listen for incoming connections.
+ boost::asio::ip::tcp::acceptor acceptor_;
+
+ /// The connection manager which owns all live connections.
+ connection_manager connection_manager_;
+
+ /// The next connection to be accepted.
+ connection_ptr new_connection_;
+
+ /// The handler for all incoming requests.
+ request_handler request_handler_;
+};
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_SERVER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server2/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/http/server2/Jamfile.v2
new file mode 100644
index 000000000..dc049c811
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/Jamfile.v2
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : connection.cpp
+ io_context_pool.cpp
+ main.cpp
+ mime_types.cpp
+ reply.cpp
+ request_handler.cpp
+ request_parser.cpp
+ server.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ /boost/thread//boost_thread
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/http/server2/connection.cpp b/src/boost/libs/asio/example/cpp03/http/server2/connection.cpp
new file mode 100644
index 000000000..6f8b02e26
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/connection.cpp
@@ -0,0 +1,93 @@
+//
+// connection.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <vector>
+#include <boost/bind/bind.hpp>
+#include "request_handler.hpp"
+
+namespace http {
+namespace server2 {
+
+connection::connection(boost::asio::io_context& io_context,
+ request_handler& handler)
+ : socket_(io_context),
+ request_handler_(handler)
+{
+}
+
+boost::asio::ip::tcp::socket& connection::socket()
+{
+ return socket_;
+}
+
+void connection::start()
+{
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ boost::bind(&connection::handle_read, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+}
+
+void connection::handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred)
+{
+ if (!e)
+ {
+ boost::tribool result;
+ boost::tie(result, boost::tuples::ignore) = request_parser_.parse(
+ request_, buffer_.data(), buffer_.data() + bytes_transferred);
+
+ if (result)
+ {
+ request_handler_.handle_request(request_, reply_);
+ boost::asio::async_write(socket_, reply_.to_buffers(),
+ boost::bind(&connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ else if (!result)
+ {
+ reply_ = reply::stock_reply(reply::bad_request);
+ boost::asio::async_write(socket_, reply_.to_buffers(),
+ boost::bind(&connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ boost::bind(&connection::handle_read, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ }
+
+ // 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::handle_write(const boost::system::error_code& e)
+{
+ if (!e)
+ {
+ // Initiate graceful connection closure.
+ boost::system::error_code ignored_ec;
+ socket_.shutdown(boost::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/src/boost/libs/asio/example/cpp03/http/server2/connection.hpp b/src/boost/libs/asio/example/cpp03/http/server2/connection.hpp
new file mode 100644
index 000000000..c949c64c3
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/connection.hpp
@@ -0,0 +1,75 @@
+//
+// connection.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/array.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#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 boost::enable_shared_from_this<connection>,
+ private boost::noncopyable
+{
+public:
+ /// Construct a connection with the given io_context.
+ explicit connection(boost::asio::io_context& io_context,
+ request_handler& handler);
+
+ /// Get the socket associated with the connection.
+ boost::asio::ip::tcp::socket& socket();
+
+ /// Start the first asynchronous operation for the connection.
+ void start();
+
+private:
+ /// Handle completion of a read operation.
+ void handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred);
+
+ /// Handle completion of a write operation.
+ void handle_write(const boost::system::error_code& e);
+
+ /// Socket for the connection.
+ boost::asio::ip::tcp::socket socket_;
+
+ /// The handler used to process the incoming request.
+ request_handler& request_handler_;
+
+ /// Buffer for incoming data.
+ boost::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 boost::shared_ptr<connection> connection_ptr;
+
+} // namespace server2
+} // namespace http
+
+#endif // HTTP_SERVER2_CONNECTION_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server2/header.hpp b/src/boost/libs/asio/example/cpp03/http/server2/header.hpp
new file mode 100644
index 000000000..80efc6cc6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/header.hpp
@@ -0,0 +1,28 @@
+//
+// header.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server2/io_context_pool.cpp b/src/boost/libs/asio/example/cpp03/http/server2/io_context_pool.cpp
new file mode 100644
index 000000000..427c22600
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/io_context_pool.cpp
@@ -0,0 +1,70 @@
+//
+// io_context_pool.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/thread/thread.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+
+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 boost::asio::io_context);
+ io_contexts_.push_back(io_context);
+ work_.push_back(boost::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<boost::shared_ptr<boost::thread> > threads;
+ for (std::size_t i = 0; i < io_contexts_.size(); ++i)
+ {
+ boost::shared_ptr<boost::thread> thread(new boost::thread(
+ boost::bind(&boost::asio::io_context::run, io_contexts_[i])));
+ threads.push_back(thread);
+ }
+
+ // 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();
+}
+
+boost::asio::io_context& io_context_pool::get_io_context()
+{
+ // Use a round-robin scheme to choose the next io_context to use.
+ boost::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/src/boost/libs/asio/example/cpp03/http/server2/io_context_pool.hpp b/src/boost/libs/asio/example/cpp03/http/server2/io_context_pool.hpp
new file mode 100644
index 000000000..86bd5b45a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/io_context_pool.hpp
@@ -0,0 +1,58 @@
+//
+// io_context_pool.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <list>
+#include <vector>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace http {
+namespace server2 {
+
+/// A pool of io_context objects.
+class io_context_pool
+ : private boost::noncopyable
+{
+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.
+ boost::asio::io_context& get_io_context();
+
+private:
+ typedef boost::shared_ptr<boost::asio::io_context> io_context_ptr;
+ typedef boost::asio::executor_work_guard<
+ boost::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/src/boost/libs/asio/example/cpp03/http/server2/main.cpp b/src/boost/libs/asio/example/cpp03/http/server2/main.cpp
new file mode 100644
index 000000000..18be4184e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/main.cpp
@@ -0,0 +1,46 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/lexical_cast.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 = boost::lexical_cast<std::size_t>(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/src/boost/libs/asio/example/cpp03/http/server2/mime_types.cpp b/src/boost/libs/asio/example/cpp03/http/server2/mime_types.cpp
new file mode 100644
index 000000000..b2fc5e7aa
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/mime_types.cpp
@@ -0,0 +1,46 @@
+//
+// mime_types.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server2/mime_types.hpp b/src/boost/libs/asio/example/cpp03/http/server2/mime_types.hpp
new file mode 100644
index 000000000..56e3fd57b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/mime_types.hpp
@@ -0,0 +1,27 @@
+//
+// mime_types.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server2/reply.cpp b/src/boost/libs/asio/example/cpp03/http/server2/reply.cpp
new file mode 100644
index 000000000..524cb65e9
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/reply.cpp
@@ -0,0 +1,256 @@
+//
+// reply.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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>
+#include <boost/lexical_cast.hpp>
+
+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";
+
+boost::asio::const_buffer to_buffer(reply::status_type status)
+{
+ switch (status)
+ {
+ case reply::ok:
+ return boost::asio::buffer(ok);
+ case reply::created:
+ return boost::asio::buffer(created);
+ case reply::accepted:
+ return boost::asio::buffer(accepted);
+ case reply::no_content:
+ return boost::asio::buffer(no_content);
+ case reply::multiple_choices:
+ return boost::asio::buffer(multiple_choices);
+ case reply::moved_permanently:
+ return boost::asio::buffer(moved_permanently);
+ case reply::moved_temporarily:
+ return boost::asio::buffer(moved_temporarily);
+ case reply::not_modified:
+ return boost::asio::buffer(not_modified);
+ case reply::bad_request:
+ return boost::asio::buffer(bad_request);
+ case reply::unauthorized:
+ return boost::asio::buffer(unauthorized);
+ case reply::forbidden:
+ return boost::asio::buffer(forbidden);
+ case reply::not_found:
+ return boost::asio::buffer(not_found);
+ case reply::internal_server_error:
+ return boost::asio::buffer(internal_server_error);
+ case reply::not_implemented:
+ return boost::asio::buffer(not_implemented);
+ case reply::bad_gateway:
+ return boost::asio::buffer(bad_gateway);
+ case reply::service_unavailable:
+ return boost::asio::buffer(service_unavailable);
+ default:
+ return boost::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<boost::asio::const_buffer> reply::to_buffers()
+{
+ std::vector<boost::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(boost::asio::buffer(h.name));
+ buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator));
+ buffers.push_back(boost::asio::buffer(h.value));
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ }
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ buffers.push_back(boost::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 = boost::lexical_cast<std::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/src/boost/libs/asio/example/cpp03/http/server2/reply.hpp b/src/boost/libs/asio/example/cpp03/http/server2/reply.hpp
new file mode 100644
index 000000000..bff15b0db
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/reply.hpp
@@ -0,0 +1,64 @@
+//
+// reply.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/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<boost::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/src/boost/libs/asio/example/cpp03/http/server2/request.hpp b/src/boost/libs/asio/example/cpp03/http/server2/request.hpp
new file mode 100644
index 000000000..197afe34a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/request.hpp
@@ -0,0 +1,34 @@
+//
+// request.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server2/request_handler.cpp b/src/boost/libs/asio/example/cpp03/http/server2/request_handler.cpp
new file mode 100644
index 000000000..ca3728b58
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/request_handler.cpp
@@ -0,0 +1,122 @@
+//
+// request_handler.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/lexical_cast.hpp>
+#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 = boost::lexical_cast<std::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/src/boost/libs/asio/example/cpp03/http/server2/request_handler.hpp b/src/boost/libs/asio/example/cpp03/http/server2/request_handler.hpp
new file mode 100644
index 000000000..dc327fdb4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/request_handler.hpp
@@ -0,0 +1,46 @@
+//
+// request_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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>
+#include <boost/noncopyable.hpp>
+
+namespace http {
+namespace server2 {
+
+struct reply;
+struct request;
+
+/// The common handler for all incoming requests.
+class request_handler
+ : private boost::noncopyable
+{
+public:
+ /// 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/src/boost/libs/asio/example/cpp03/http/server2/request_parser.cpp b/src/boost/libs/asio/example/cpp03/http/server2/request_parser.cpp
new file mode 100644
index 000000000..8533e8873
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/request_parser.cpp
@@ -0,0 +1,315 @@
+//
+// request_parser.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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;
+}
+
+boost::tribool request_parser::consume(request& req, char input)
+{
+ switch (state_)
+ {
+ case method_start:
+ if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ state_ = method;
+ req.method.push_back(input);
+ return boost::indeterminate;
+ }
+ case method:
+ if (input == ' ')
+ {
+ state_ = uri;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.method.push_back(input);
+ return boost::indeterminate;
+ }
+ case uri:
+ if (input == ' ')
+ {
+ state_ = http_version_h;
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.uri.push_back(input);
+ return boost::indeterminate;
+ }
+ case http_version_h:
+ if (input == 'H')
+ {
+ state_ = http_version_t_1;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_t_1:
+ if (input == 'T')
+ {
+ state_ = http_version_t_2;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_t_2:
+ if (input == 'T')
+ {
+ state_ = http_version_p;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_p:
+ if (input == 'P')
+ {
+ state_ = http_version_slash;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_slash:
+ if (input == '/')
+ {
+ req.http_version_major = 0;
+ req.http_version_minor = 0;
+ state_ = http_version_major_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ 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 boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_major:
+ if (input == '.')
+ {
+ state_ = http_version_minor_start;
+ return boost::indeterminate;
+ }
+ else if (is_digit(input))
+ {
+ req.http_version_major = req.http_version_major * 10 + input - '0';
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ 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 boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_minor:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_1;
+ return boost::indeterminate;
+ }
+ else if (is_digit(input))
+ {
+ req.http_version_minor = req.http_version_minor * 10 + input - '0';
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case expecting_newline_1:
+ if (input == '\n')
+ {
+ state_ = header_line_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case header_line_start:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_3;
+ return boost::indeterminate;
+ }
+ else if (!req.headers.empty() && (input == ' ' || input == '\t'))
+ {
+ state_ = header_lws;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.push_back(header());
+ req.headers.back().name.push_back(input);
+ state_ = header_name;
+ return boost::indeterminate;
+ }
+ case header_lws:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_2;
+ return boost::indeterminate;
+ }
+ else if (input == ' ' || input == '\t')
+ {
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ state_ = header_value;
+ req.headers.back().value.push_back(input);
+ return boost::indeterminate;
+ }
+ case header_name:
+ if (input == ':')
+ {
+ state_ = space_before_header_value;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.back().name.push_back(input);
+ return boost::indeterminate;
+ }
+ case space_before_header_value:
+ if (input == ' ')
+ {
+ state_ = header_value;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case header_value:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_2;
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.back().value.push_back(input);
+ return boost::indeterminate;
+ }
+ case expecting_newline_2:
+ if (input == '\n')
+ {
+ state_ = header_line_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case expecting_newline_3:
+ return (input == '\n');
+ default:
+ return false;
+ }
+}
+
+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/src/boost/libs/asio/example/cpp03/http/server2/request_parser.hpp b/src/boost/libs/asio/example/cpp03/http/server2/request_parser.hpp
new file mode 100644
index 000000000..3d9aae7a9
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/request_parser.hpp
@@ -0,0 +1,95 @@
+//
+// request_parser.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/logic/tribool.hpp>
+#include <boost/tuple/tuple.hpp>
+
+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();
+
+ /// Parse some data. The tribool return value is true when a complete request
+ /// has been parsed, false 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>
+ boost::tuple<boost::tribool, InputIterator> parse(request& req,
+ InputIterator begin, InputIterator end)
+ {
+ while (begin != end)
+ {
+ boost::tribool result = consume(req, *begin++);
+ if (result || !result)
+ return boost::make_tuple(result, begin);
+ }
+ boost::tribool result = boost::indeterminate;
+ return boost::make_tuple(result, begin);
+ }
+
+private:
+ /// Handle the next character of input.
+ boost::tribool 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/src/boost/libs/asio/example/cpp03/http/server2/server.cpp b/src/boost/libs/asio/example/cpp03/http/server2/server.cpp
new file mode 100644
index 000000000..c6fa33ca1
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/server.cpp
@@ -0,0 +1,77 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/bind/bind.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()),
+ new_connection_(),
+ 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)
+ signals_.async_wait(boost::bind(&server::handle_stop, this));
+
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+ boost::asio::ip::tcp::resolver resolver(acceptor_.get_executor());
+ boost::asio::ip::tcp::endpoint endpoint =
+ *resolver.resolve(address, port).begin();
+ acceptor_.open(endpoint.protocol());
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor_.bind(endpoint);
+ acceptor_.listen();
+
+ start_accept();
+}
+
+void server::run()
+{
+ io_context_pool_.run();
+}
+
+void server::start_accept()
+{
+ new_connection_.reset(new connection(
+ io_context_pool_.get_io_context(), request_handler_));
+ acceptor_.async_accept(new_connection_->socket(),
+ boost::bind(&server::handle_accept, this,
+ boost::asio::placeholders::error));
+}
+
+void server::handle_accept(const boost::system::error_code& e)
+{
+ if (!e)
+ {
+ new_connection_->start();
+ }
+
+ start_accept();
+}
+
+void server::handle_stop()
+{
+ io_context_pool_.stop();
+}
+
+} // namespace server2
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server2/server.hpp b/src/boost/libs/asio/example/cpp03/http/server2/server.hpp
new file mode 100644
index 000000000..90b921f4e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server2/server.hpp
@@ -0,0 +1,68 @@
+//
+// server.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <string>
+#include <vector>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include "connection.hpp"
+#include "io_context_pool.hpp"
+#include "request_handler.hpp"
+
+namespace http {
+namespace server2 {
+
+/// The top-level class of the HTTP server.
+class server
+ : private boost::noncopyable
+{
+public:
+ /// 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:
+ /// Initiate an asynchronous accept operation.
+ void start_accept();
+
+ /// Handle completion of an asynchronous accept operation.
+ void handle_accept(const boost::system::error_code& e);
+
+ /// Handle a request to stop the server.
+ void handle_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.
+ boost::asio::signal_set signals_;
+
+ /// Acceptor used to listen for incoming connections.
+ boost::asio::ip::tcp::acceptor acceptor_;
+
+ /// The next connection to be accepted.
+ connection_ptr new_connection_;
+
+ /// The handler for all incoming requests.
+ request_handler request_handler_;
+};
+
+} // namespace server2
+} // namespace http
+
+#endif // HTTP_SERVER2_SERVER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server3/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/http/server3/Jamfile.v2
new file mode 100644
index 000000000..e49656ec5
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/Jamfile.v2
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : connection.cpp
+ main.cpp
+ mime_types.cpp
+ reply.cpp
+ request_handler.cpp
+ request_parser.cpp
+ server.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ /boost/thread//boost_thread
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/http/server3/connection.cpp b/src/boost/libs/asio/example/cpp03/http/server3/connection.cpp
new file mode 100644
index 000000000..fa6f828a9
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/connection.cpp
@@ -0,0 +1,94 @@
+//
+// connection.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <vector>
+#include <boost/bind/bind.hpp>
+#include "request_handler.hpp"
+
+namespace http {
+namespace server3 {
+
+connection::connection(boost::asio::io_context& io_context,
+ request_handler& handler)
+ : strand_(boost::asio::make_strand(io_context)),
+ socket_(strand_),
+ request_handler_(handler)
+{
+}
+
+boost::asio::ip::tcp::socket& connection::socket()
+{
+ return socket_;
+}
+
+void connection::start()
+{
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ boost::bind(&connection::handle_read, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+}
+
+void connection::handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred)
+{
+ if (!e)
+ {
+ boost::tribool result;
+ boost::tie(result, boost::tuples::ignore) = request_parser_.parse(
+ request_, buffer_.data(), buffer_.data() + bytes_transferred);
+
+ if (result)
+ {
+ request_handler_.handle_request(request_, reply_);
+ boost::asio::async_write(socket_, reply_.to_buffers(),
+ boost::bind(&connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ else if (!result)
+ {
+ reply_ = reply::stock_reply(reply::bad_request);
+ boost::asio::async_write(socket_, reply_.to_buffers(),
+ boost::bind(&connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ boost::bind(&connection::handle_read, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ }
+
+ // 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::handle_write(const boost::system::error_code& e)
+{
+ if (!e)
+ {
+ // Initiate graceful connection closure.
+ boost::system::error_code ignored_ec;
+ socket_.shutdown(boost::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/src/boost/libs/asio/example/cpp03/http/server3/connection.hpp b/src/boost/libs/asio/example/cpp03/http/server3/connection.hpp
new file mode 100644
index 000000000..f5583d02f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/connection.hpp
@@ -0,0 +1,78 @@
+//
+// connection.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/array.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#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 boost::enable_shared_from_this<connection>,
+ private boost::noncopyable
+{
+public:
+ /// Construct a connection with the given io_context.
+ explicit connection(boost::asio::io_context& io_context,
+ request_handler& handler);
+
+ /// Get the socket associated with the connection.
+ boost::asio::ip::tcp::socket& socket();
+
+ /// Start the first asynchronous operation for the connection.
+ void start();
+
+private:
+ /// Handle completion of a read operation.
+ void handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred);
+
+ /// Handle completion of a write operation.
+ void handle_write(const boost::system::error_code& e);
+
+ /// Strand to ensure the connection's handlers are not called concurrently.
+ boost::asio::strand<boost::asio::io_context::executor_type> strand_;
+
+ /// Socket for the connection.
+ boost::asio::ip::tcp::socket socket_;
+
+ /// The handler used to process the incoming request.
+ request_handler& request_handler_;
+
+ /// Buffer for incoming data.
+ boost::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 boost::shared_ptr<connection> connection_ptr;
+
+} // namespace server3
+} // namespace http
+
+#endif // HTTP_SERVER3_CONNECTION_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server3/header.hpp b/src/boost/libs/asio/example/cpp03/http/server3/header.hpp
new file mode 100644
index 000000000..45a98a4bb
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/header.hpp
@@ -0,0 +1,28 @@
+//
+// header.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server3/main.cpp b/src/boost/libs/asio/example/cpp03/http/server3/main.cpp
new file mode 100644
index 000000000..4f181c573
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/main.cpp
@@ -0,0 +1,46 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/lexical_cast.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 = boost::lexical_cast<std::size_t>(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/src/boost/libs/asio/example/cpp03/http/server3/mime_types.cpp b/src/boost/libs/asio/example/cpp03/http/server3/mime_types.cpp
new file mode 100644
index 000000000..028970c10
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/mime_types.cpp
@@ -0,0 +1,46 @@
+//
+// mime_types.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server3/mime_types.hpp b/src/boost/libs/asio/example/cpp03/http/server3/mime_types.hpp
new file mode 100644
index 000000000..9558f5e83
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/mime_types.hpp
@@ -0,0 +1,27 @@
+//
+// mime_types.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server3/reply.cpp b/src/boost/libs/asio/example/cpp03/http/server3/reply.cpp
new file mode 100644
index 000000000..0d4639200
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/reply.cpp
@@ -0,0 +1,256 @@
+//
+// reply.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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>
+#include <boost/lexical_cast.hpp>
+
+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";
+
+boost::asio::const_buffer to_buffer(reply::status_type status)
+{
+ switch (status)
+ {
+ case reply::ok:
+ return boost::asio::buffer(ok);
+ case reply::created:
+ return boost::asio::buffer(created);
+ case reply::accepted:
+ return boost::asio::buffer(accepted);
+ case reply::no_content:
+ return boost::asio::buffer(no_content);
+ case reply::multiple_choices:
+ return boost::asio::buffer(multiple_choices);
+ case reply::moved_permanently:
+ return boost::asio::buffer(moved_permanently);
+ case reply::moved_temporarily:
+ return boost::asio::buffer(moved_temporarily);
+ case reply::not_modified:
+ return boost::asio::buffer(not_modified);
+ case reply::bad_request:
+ return boost::asio::buffer(bad_request);
+ case reply::unauthorized:
+ return boost::asio::buffer(unauthorized);
+ case reply::forbidden:
+ return boost::asio::buffer(forbidden);
+ case reply::not_found:
+ return boost::asio::buffer(not_found);
+ case reply::internal_server_error:
+ return boost::asio::buffer(internal_server_error);
+ case reply::not_implemented:
+ return boost::asio::buffer(not_implemented);
+ case reply::bad_gateway:
+ return boost::asio::buffer(bad_gateway);
+ case reply::service_unavailable:
+ return boost::asio::buffer(service_unavailable);
+ default:
+ return boost::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<boost::asio::const_buffer> reply::to_buffers()
+{
+ std::vector<boost::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(boost::asio::buffer(h.name));
+ buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator));
+ buffers.push_back(boost::asio::buffer(h.value));
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ }
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ buffers.push_back(boost::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 = boost::lexical_cast<std::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/src/boost/libs/asio/example/cpp03/http/server3/reply.hpp b/src/boost/libs/asio/example/cpp03/http/server3/reply.hpp
new file mode 100644
index 000000000..201578576
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/reply.hpp
@@ -0,0 +1,64 @@
+//
+// reply.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/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<boost::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/src/boost/libs/asio/example/cpp03/http/server3/request.hpp b/src/boost/libs/asio/example/cpp03/http/server3/request.hpp
new file mode 100644
index 000000000..300d379cc
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/request.hpp
@@ -0,0 +1,34 @@
+//
+// request.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server3/request_handler.cpp b/src/boost/libs/asio/example/cpp03/http/server3/request_handler.cpp
new file mode 100644
index 000000000..3046989f4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/request_handler.cpp
@@ -0,0 +1,122 @@
+//
+// request_handler.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/lexical_cast.hpp>
+#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 = boost::lexical_cast<std::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/src/boost/libs/asio/example/cpp03/http/server3/request_handler.hpp b/src/boost/libs/asio/example/cpp03/http/server3/request_handler.hpp
new file mode 100644
index 000000000..75d415716
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/request_handler.hpp
@@ -0,0 +1,46 @@
+//
+// request_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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>
+#include <boost/noncopyable.hpp>
+
+namespace http {
+namespace server3 {
+
+struct reply;
+struct request;
+
+/// The common handler for all incoming requests.
+class request_handler
+ : private boost::noncopyable
+{
+public:
+ /// 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/src/boost/libs/asio/example/cpp03/http/server3/request_parser.cpp b/src/boost/libs/asio/example/cpp03/http/server3/request_parser.cpp
new file mode 100644
index 000000000..d70645512
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/request_parser.cpp
@@ -0,0 +1,315 @@
+//
+// request_parser.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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;
+}
+
+boost::tribool request_parser::consume(request& req, char input)
+{
+ switch (state_)
+ {
+ case method_start:
+ if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ state_ = method;
+ req.method.push_back(input);
+ return boost::indeterminate;
+ }
+ case method:
+ if (input == ' ')
+ {
+ state_ = uri;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.method.push_back(input);
+ return boost::indeterminate;
+ }
+ case uri:
+ if (input == ' ')
+ {
+ state_ = http_version_h;
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.uri.push_back(input);
+ return boost::indeterminate;
+ }
+ case http_version_h:
+ if (input == 'H')
+ {
+ state_ = http_version_t_1;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_t_1:
+ if (input == 'T')
+ {
+ state_ = http_version_t_2;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_t_2:
+ if (input == 'T')
+ {
+ state_ = http_version_p;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_p:
+ if (input == 'P')
+ {
+ state_ = http_version_slash;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_slash:
+ if (input == '/')
+ {
+ req.http_version_major = 0;
+ req.http_version_minor = 0;
+ state_ = http_version_major_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ 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 boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_major:
+ if (input == '.')
+ {
+ state_ = http_version_minor_start;
+ return boost::indeterminate;
+ }
+ else if (is_digit(input))
+ {
+ req.http_version_major = req.http_version_major * 10 + input - '0';
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ 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 boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case http_version_minor:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_1;
+ return boost::indeterminate;
+ }
+ else if (is_digit(input))
+ {
+ req.http_version_minor = req.http_version_minor * 10 + input - '0';
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case expecting_newline_1:
+ if (input == '\n')
+ {
+ state_ = header_line_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case header_line_start:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_3;
+ return boost::indeterminate;
+ }
+ else if (!req.headers.empty() && (input == ' ' || input == '\t'))
+ {
+ state_ = header_lws;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.push_back(header());
+ req.headers.back().name.push_back(input);
+ state_ = header_name;
+ return boost::indeterminate;
+ }
+ case header_lws:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_2;
+ return boost::indeterminate;
+ }
+ else if (input == ' ' || input == '\t')
+ {
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ state_ = header_value;
+ req.headers.back().value.push_back(input);
+ return boost::indeterminate;
+ }
+ case header_name:
+ if (input == ':')
+ {
+ state_ = space_before_header_value;
+ return boost::indeterminate;
+ }
+ else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.back().name.push_back(input);
+ return boost::indeterminate;
+ }
+ case space_before_header_value:
+ if (input == ' ')
+ {
+ state_ = header_value;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case header_value:
+ if (input == '\r')
+ {
+ state_ = expecting_newline_2;
+ return boost::indeterminate;
+ }
+ else if (is_ctl(input))
+ {
+ return false;
+ }
+ else
+ {
+ req.headers.back().value.push_back(input);
+ return boost::indeterminate;
+ }
+ case expecting_newline_2:
+ if (input == '\n')
+ {
+ state_ = header_line_start;
+ return boost::indeterminate;
+ }
+ else
+ {
+ return false;
+ }
+ case expecting_newline_3:
+ return (input == '\n');
+ default:
+ return false;
+ }
+}
+
+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/src/boost/libs/asio/example/cpp03/http/server3/request_parser.hpp b/src/boost/libs/asio/example/cpp03/http/server3/request_parser.hpp
new file mode 100644
index 000000000..f3ae654f4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/request_parser.hpp
@@ -0,0 +1,95 @@
+//
+// request_parser.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/logic/tribool.hpp>
+#include <boost/tuple/tuple.hpp>
+
+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();
+
+ /// Parse some data. The tribool return value is true when a complete request
+ /// has been parsed, false 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>
+ boost::tuple<boost::tribool, InputIterator> parse(request& req,
+ InputIterator begin, InputIterator end)
+ {
+ while (begin != end)
+ {
+ boost::tribool result = consume(req, *begin++);
+ if (result || !result)
+ return boost::make_tuple(result, begin);
+ }
+ boost::tribool result = boost::indeterminate;
+ return boost::make_tuple(result, begin);
+ }
+
+private:
+ /// Handle the next character of input.
+ boost::tribool 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/src/boost/libs/asio/example/cpp03/http/server3/server.cpp b/src/boost/libs/asio/example/cpp03/http/server3/server.cpp
new file mode 100644
index 000000000..8035d3167
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/server.cpp
@@ -0,0 +1,90 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/thread/thread.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+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_),
+ new_connection_(),
+ 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)
+ signals_.async_wait(boost::bind(&server::handle_stop, this));
+
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+ boost::asio::ip::tcp::resolver resolver(io_context_);
+ boost::asio::ip::tcp::endpoint endpoint =
+ *resolver.resolve(address, port).begin();
+ acceptor_.open(endpoint.protocol());
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor_.bind(endpoint);
+ acceptor_.listen();
+
+ start_accept();
+}
+
+void server::run()
+{
+ // Create a pool of threads to run all of the io_contexts.
+ std::vector<boost::shared_ptr<boost::thread> > threads;
+ for (std::size_t i = 0; i < thread_pool_size_; ++i)
+ {
+ boost::shared_ptr<boost::thread> thread(new boost::thread(
+ boost::bind(&boost::asio::io_context::run, &io_context_)));
+ threads.push_back(thread);
+ }
+
+ // Wait for all threads in the pool to exit.
+ for (std::size_t i = 0; i < threads.size(); ++i)
+ threads[i]->join();
+}
+
+void server::start_accept()
+{
+ new_connection_.reset(new connection(io_context_, request_handler_));
+ acceptor_.async_accept(new_connection_->socket(),
+ boost::bind(&server::handle_accept, this,
+ boost::asio::placeholders::error));
+}
+
+void server::handle_accept(const boost::system::error_code& e)
+{
+ if (!e)
+ {
+ new_connection_->start();
+ }
+
+ start_accept();
+}
+
+void server::handle_stop()
+{
+ io_context_.stop();
+}
+
+} // namespace server3
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server3/server.hpp b/src/boost/libs/asio/example/cpp03/http/server3/server.hpp
new file mode 100644
index 000000000..fc7c21d37
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server3/server.hpp
@@ -0,0 +1,70 @@
+//
+// server.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <string>
+#include <vector>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include "connection.hpp"
+#include "request_handler.hpp"
+
+namespace http {
+namespace server3 {
+
+/// The top-level class of the HTTP server.
+class server
+ : private boost::noncopyable
+{
+public:
+ /// 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:
+ /// Initiate an asynchronous accept operation.
+ void start_accept();
+
+ /// Handle completion of an asynchronous accept operation.
+ void handle_accept(const boost::system::error_code& e);
+
+ /// Handle a request to stop the server.
+ void handle_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.
+ boost::asio::io_context io_context_;
+
+ /// The signal_set is used to register for process termination notifications.
+ boost::asio::signal_set signals_;
+
+ /// Acceptor used to listen for incoming connections.
+ boost::asio::ip::tcp::acceptor acceptor_;
+
+ /// The next connection to be accepted.
+ connection_ptr new_connection_;
+
+ /// The handler for all incoming requests.
+ request_handler request_handler_;
+};
+
+} // namespace server3
+} // namespace http
+
+#endif // HTTP_SERVER3_SERVER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server4/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/http/server4/Jamfile.v2
new file mode 100644
index 000000000..c103f1217
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/Jamfile.v2
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : file_handler.cpp
+ main.cpp
+ mime_types.cpp
+ reply.cpp
+ request_parser.cpp
+ server.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ /boost/thread//boost_thread
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/http/server4/file_handler.cpp b/src/boost/libs/asio/example/cpp03/http/server4/file_handler.cpp
new file mode 100644
index 000000000..49537f9b6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/file_handler.cpp
@@ -0,0 +1,122 @@
+//
+// file_handler.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/lexical_cast.hpp>
+#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 = boost::lexical_cast<std::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/src/boost/libs/asio/example/cpp03/http/server4/file_handler.hpp b/src/boost/libs/asio/example/cpp03/http/server4/file_handler.hpp
new file mode 100644
index 000000000..ff9f0f887
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/file_handler.hpp
@@ -0,0 +1,44 @@
+//
+// file_handler.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server4/header.hpp b/src/boost/libs/asio/example/cpp03/http/server4/header.hpp
new file mode 100644
index 000000000..5a1373e21
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/header.hpp
@@ -0,0 +1,28 @@
+//
+// header.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server4/main.cpp b/src/boost/libs/asio/example/cpp03/http/server4/main.cpp
new file mode 100644
index 000000000..50efacd22
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/main.cpp
@@ -0,0 +1,58 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.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;
+ }
+
+ boost::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.
+ boost::asio::signal_set signals(io_context);
+ signals.add(SIGINT);
+ signals.add(SIGTERM);
+#if defined(SIGQUIT)
+ signals.add(SIGQUIT);
+#endif // defined(SIGQUIT)
+ signals.async_wait(boost::bind(
+ &boost::asio::io_context::stop, &io_context));
+
+ // Run the server.
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/http/server4/mime_types.cpp b/src/boost/libs/asio/example/cpp03/http/server4/mime_types.cpp
new file mode 100644
index 000000000..0d8ea5d5a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/mime_types.cpp
@@ -0,0 +1,46 @@
+//
+// mime_types.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server4/mime_types.hpp b/src/boost/libs/asio/example/cpp03/http/server4/mime_types.hpp
new file mode 100644
index 000000000..d92ba1283
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/mime_types.hpp
@@ -0,0 +1,27 @@
+//
+// mime_types.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/http/server4/reply.cpp b/src/boost/libs/asio/example/cpp03/http/server4/reply.cpp
new file mode 100644
index 000000000..be9481aeb
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/reply.cpp
@@ -0,0 +1,256 @@
+//
+// reply.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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>
+#include <boost/lexical_cast.hpp>
+
+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";
+
+boost::asio::const_buffer to_buffer(reply::status_type status)
+{
+ switch (status)
+ {
+ case reply::ok:
+ return boost::asio::buffer(ok);
+ case reply::created:
+ return boost::asio::buffer(created);
+ case reply::accepted:
+ return boost::asio::buffer(accepted);
+ case reply::no_content:
+ return boost::asio::buffer(no_content);
+ case reply::multiple_choices:
+ return boost::asio::buffer(multiple_choices);
+ case reply::moved_permanently:
+ return boost::asio::buffer(moved_permanently);
+ case reply::moved_temporarily:
+ return boost::asio::buffer(moved_temporarily);
+ case reply::not_modified:
+ return boost::asio::buffer(not_modified);
+ case reply::bad_request:
+ return boost::asio::buffer(bad_request);
+ case reply::unauthorized:
+ return boost::asio::buffer(unauthorized);
+ case reply::forbidden:
+ return boost::asio::buffer(forbidden);
+ case reply::not_found:
+ return boost::asio::buffer(not_found);
+ case reply::internal_server_error:
+ return boost::asio::buffer(internal_server_error);
+ case reply::not_implemented:
+ return boost::asio::buffer(not_implemented);
+ case reply::bad_gateway:
+ return boost::asio::buffer(bad_gateway);
+ case reply::service_unavailable:
+ return boost::asio::buffer(service_unavailable);
+ default:
+ return boost::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<boost::asio::const_buffer> reply::to_buffers()
+{
+ std::vector<boost::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(boost::asio::buffer(h.name));
+ buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator));
+ buffers.push_back(boost::asio::buffer(h.value));
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ }
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ buffers.push_back(boost::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 = boost::lexical_cast<std::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/src/boost/libs/asio/example/cpp03/http/server4/reply.hpp b/src/boost/libs/asio/example/cpp03/http/server4/reply.hpp
new file mode 100644
index 000000000..6ca1d635d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/reply.hpp
@@ -0,0 +1,64 @@
+//
+// reply.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/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<boost::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/src/boost/libs/asio/example/cpp03/http/server4/request.hpp b/src/boost/libs/asio/example/cpp03/http/server4/request.hpp
new file mode 100644
index 000000000..a50a21fd2
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/request.hpp
@@ -0,0 +1,46 @@
+//
+// request.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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
+{
+ /// The request method, e.g. "GET", "POST".
+ std::string method;
+
+ /// The requested URI, such as a path to a file.
+ std::string uri;
+
+ /// Major version number, usually 1.
+ int http_version_major;
+
+ /// Minor version number, usually 0 or 1.
+ int http_version_minor;
+
+ /// The headers included with the request.
+ std::vector<header> headers;
+
+ /// The optional content sent with the request.
+ std::string content;
+};
+
+} // namespace server4
+} // namespace http
+
+#endif // HTTP_SERVER4_REQUEST_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server4/request_parser.cpp b/src/boost/libs/asio/example/cpp03/http/server4/request_parser.cpp
new file mode 100644
index 000000000..17f0abb1c
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/request_parser.cpp
@@ -0,0 +1,226 @@
+//
+// request_parser.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <algorithm>
+#include <cctype>
+#include <boost/lexical_cast.hpp>
+#include "request.hpp"
+
+namespace http {
+namespace server4 {
+
+// Enable the pseudo-keywords reenter, yield and fork.
+#include <boost/asio/yield.hpp>
+
+std::string request_parser::content_length_name_ = "Content-Length";
+
+boost::tribool request_parser::consume(request& req, char c)
+{
+ reenter (this)
+ {
+ req.method.clear();
+ req.uri.clear();
+ req.http_version_major = 0;
+ req.http_version_minor = 0;
+ req.headers.clear();
+ req.content.clear();
+ content_length_ = 0;
+
+ // Request method.
+ while (is_char(c) && !is_ctl(c) && !is_tspecial(c) && c != ' ')
+ {
+ req.method.push_back(c);
+ yield return boost::indeterminate;
+ }
+ if (req.method.empty())
+ return false;
+
+ // Space.
+ if (c != ' ') return false;
+ yield return boost::indeterminate;
+
+ // URI.
+ while (!is_ctl(c) && c != ' ')
+ {
+ req.uri.push_back(c);
+ yield return boost::indeterminate;
+ }
+ if (req.uri.empty()) return false;
+
+ // Space.
+ if (c != ' ') return false;
+ yield return boost::indeterminate;
+
+ // HTTP protocol identifier.
+ if (c != 'H') return false;
+ yield return boost::indeterminate;
+ if (c != 'T') return false;
+ yield return boost::indeterminate;
+ if (c != 'T') return false;
+ yield return boost::indeterminate;
+ if (c != 'P') return false;
+ yield return boost::indeterminate;
+
+ // Slash.
+ if (c != '/') return false;
+ yield return boost::indeterminate;
+
+ // Major version number.
+ if (!is_digit(c)) return false;
+ while (is_digit(c))
+ {
+ req.http_version_major = req.http_version_major * 10 + c - '0';
+ yield return boost::indeterminate;
+ }
+
+ // Dot.
+ if (c != '.') return false;
+ yield return boost::indeterminate;
+
+ // Minor version number.
+ if (!is_digit(c)) return false;
+ while (is_digit(c))
+ {
+ req.http_version_minor = req.http_version_minor * 10 + c - '0';
+ yield return boost::indeterminate;
+ }
+
+ // CRLF.
+ if (c != '\r') return false;
+ yield return boost::indeterminate;
+ if (c != '\n') return false;
+ yield return boost::indeterminate;
+
+ // Headers.
+ while ((is_char(c) && !is_ctl(c) && !is_tspecial(c) && c != '\r')
+ || (c == ' ' || c == '\t'))
+ {
+ if (c == ' ' || c == '\t')
+ {
+ // Leading whitespace. Must be continuation of previous header's value.
+ if (req.headers.empty()) return false;
+ while (c == ' ' || c == '\t')
+ yield return boost::indeterminate;
+ }
+ else
+ {
+ // Start the next header.
+ req.headers.push_back(header());
+
+ // Header name.
+ while (is_char(c) && !is_ctl(c) && !is_tspecial(c) && c != ':')
+ {
+ req.headers.back().name.push_back(c);
+ yield return boost::indeterminate;
+ }
+
+ // Colon and space separates the header name from the header value.
+ if (c != ':') return false;
+ yield return boost::indeterminate;
+ if (c != ' ') return false;
+ yield return boost::indeterminate;
+ }
+
+ // Header value.
+ while (is_char(c) && !is_ctl(c) && c != '\r')
+ {
+ req.headers.back().value.push_back(c);
+ yield return boost::indeterminate;
+ }
+
+ // CRLF.
+ if (c != '\r') return false;
+ yield return boost::indeterminate;
+ if (c != '\n') return false;
+ yield return boost::indeterminate;
+ }
+
+ // CRLF.
+ if (c != '\r') return false;
+ yield return boost::indeterminate;
+ if (c != '\n') return false;
+
+ // Check for optional Content-Length header.
+ for (std::size_t i = 0; i < req.headers.size(); ++i)
+ {
+ if (headers_equal(req.headers[i].name, content_length_name_))
+ {
+ try
+ {
+ content_length_ =
+ boost::lexical_cast<std::size_t>(req.headers[i].value);
+ }
+ catch (boost::bad_lexical_cast&)
+ {
+ return false;
+ }
+ }
+ }
+
+ // Content.
+ while (req.content.size() < content_length_)
+ {
+ yield return boost::indeterminate;
+ req.content.push_back(c);
+ }
+ }
+
+ return true;
+}
+
+// Disable the pseudo-keywords reenter, yield and fork.
+#include <boost/asio/unyield.hpp>
+
+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';
+}
+
+bool request_parser::tolower_compare(char a, char b)
+{
+ return std::tolower(a) == std::tolower(b);
+}
+
+bool request_parser::headers_equal(const std::string& a, const std::string& b)
+{
+ if (a.length() != b.length())
+ return false;
+
+ return std::equal(a.begin(), a.end(), b.begin(),
+ &request_parser::tolower_compare);
+}
+
+} // namespace server4
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server4/request_parser.hpp b/src/boost/libs/asio/example/cpp03/http/server4/request_parser.hpp
new file mode 100644
index 000000000..f7beaebd4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/request_parser.hpp
@@ -0,0 +1,78 @@
+//
+// request_parser.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <string>
+#include <boost/logic/tribool.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/asio/coroutine.hpp>
+
+namespace http {
+namespace server4 {
+
+struct request;
+
+/// Parser for incoming requests.
+class request_parser : boost::asio::coroutine
+{
+public:
+ /// Parse some data. The tribool return value is true when a complete request
+ /// has been parsed, false 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>
+ boost::tuple<boost::tribool, InputIterator> parse(request& req,
+ InputIterator begin, InputIterator end)
+ {
+ while (begin != end)
+ {
+ boost::tribool result = consume(req, *begin++);
+ if (result || !result)
+ return boost::make_tuple(result, begin);
+ }
+ boost::tribool result = boost::indeterminate;
+ return boost::make_tuple(result, begin);
+ }
+
+private:
+ /// The name of the content length header.
+ static std::string content_length_name_;
+
+ /// Content length as decoded from headers. Defaults to 0.
+ std::size_t content_length_;
+
+ /// Handle the next character of input.
+ boost::tribool 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);
+
+ /// Check if two characters are equal, without regard to case.
+ static bool tolower_compare(char a, char b);
+
+ /// Check whether the two request header names match.
+ bool headers_equal(const std::string& a, const std::string& b);
+};
+
+} // namespace server4
+} // namespace http
+
+#endif // HTTP_SERVER4_REQUEST_PARSER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/http/server4/server.cpp b/src/boost/libs/asio/example/cpp03/http/server4/server.cpp
new file mode 100644
index 000000000..b6d109cad
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/server.cpp
@@ -0,0 +1,122 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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(boost::asio::io_context& io_context,
+ const std::string& address, const std::string& port,
+ boost::function<void(const request&, reply&)> request_handler)
+ : request_handler_(request_handler)
+{
+ tcp::resolver resolver(io_context);
+ boost::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 <boost/asio/yield.hpp>
+
+void server::operator()(boost::system::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 boost::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(boost::asio::buffer(*buffer_), *this);
+
+ // Parse the data we just received.
+ boost::tie(valid_request_, boost::tuples::ignore)
+ = request_parser_.parse(*request_,
+ buffer_->data(), buffer_->data() + length);
+
+ // An indeterminate result means we need more data, so keep looping.
+ } while (boost::indeterminate(valid_request_));
+
+ // Create the reply object that will be sent back to the client.
+ reply_.reset(new reply);
+
+ if (valid_request_)
+ {
+ // 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 boost::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 <boost/asio/unyield.hpp>
+
+} // namespace server4
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp03/http/server4/server.hpp b/src/boost/libs/asio/example/cpp03/http/server4/server.hpp
new file mode 100644
index 000000000..5be1f250a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/http/server4/server.hpp
@@ -0,0 +1,73 @@
+//
+// server.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <string>
+#include <boost/array.hpp>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include "request_parser.hpp"
+
+namespace http {
+namespace server4 {
+
+struct request;
+struct reply;
+
+/// The top-level coroutine of the HTTP server.
+class server : boost::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(boost::asio::io_context& io_context,
+ const std::string& address, const std::string& port,
+ boost::function<void(const request&, reply&)> request_handler);
+
+ /// Perform work associated with the server.
+ void operator()(
+ boost::system::error_code ec = boost::system::error_code(),
+ std::size_t length = 0);
+
+private:
+ typedef boost::asio::ip::tcp tcp;
+
+ /// The user-supplied handler for all incoming requests.
+ boost::function<void(const request&, reply&)> request_handler_;
+
+ /// Acceptor used to listen for incoming connections.
+ boost::shared_ptr<tcp::acceptor> acceptor_;
+
+ /// The current connection from a client.
+ boost::shared_ptr<tcp::socket> socket_;
+
+ /// Buffer for incoming data.
+ boost::shared_ptr<boost::array<char, 8192> > buffer_;
+
+ /// The incoming request.
+ boost::shared_ptr<request> request_;
+
+ /// Whether the request is valid or not.
+ boost::tribool valid_request_;
+
+ /// The parser for the incoming request.
+ request_parser request_parser_;
+
+ /// The reply to be sent back to the client.
+ boost::shared_ptr<reply> reply_;
+};
+
+} // namespace server4
+} // namespace http
+
+#endif // HTTP_SERVER4_SERVER_HPP
diff --git a/src/boost/libs/asio/example/cpp03/icmp/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/icmp/Jamfile.v2
new file mode 100644
index 000000000..a7a2ac60d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/icmp/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe ping
+ : ping.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/icmp/icmp_header.hpp b/src/boost/libs/asio/example/cpp03/icmp/icmp_header.hpp
new file mode 100644
index 000000000..ddb992e62
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/icmp/icmp_header.hpp
@@ -0,0 +1,94 @@
+//
+// icmp_header.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/icmp/ipv4_header.hpp b/src/boost/libs/asio/example/cpp03/icmp/ipv4_header.hpp
new file mode 100644
index 000000000..56adc2494
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/icmp/ipv4_header.hpp
@@ -0,0 +1,102 @@
+//
+// ipv4_header.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/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); }
+
+ boost::asio::ip::address_v4 source_address() const
+ {
+ boost::asio::ip::address_v4::bytes_type bytes
+ = { { rep_[12], rep_[13], rep_[14], rep_[15] } };
+ return boost::asio::ip::address_v4(bytes);
+ }
+
+ boost::asio::ip::address_v4 destination_address() const
+ {
+ boost::asio::ip::address_v4::bytes_type bytes
+ = { { rep_[16], rep_[17], rep_[18], rep_[19] } };
+ return boost::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/src/boost/libs/asio/example/cpp03/icmp/ping.cpp b/src/boost/libs/asio/example/cpp03/icmp/ping.cpp
new file mode 100644
index 000000000..7a3bfea21
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/icmp/ping.cpp
@@ -0,0 +1,163 @@
+//
+// ping.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include <istream>
+#include <iostream>
+#include <ostream>
+
+#include "icmp_header.hpp"
+#include "ipv4_header.hpp"
+
+using boost::asio::ip::icmp;
+using boost::asio::steady_timer;
+namespace chrono = boost::asio::chrono;
+
+class pinger
+{
+public:
+ pinger(boost::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.
+ boost::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(boost::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(boost::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),
+ boost::bind(&pinger::handle_receive, this, boost::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(BOOST_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_;
+ boost::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(BOOST_ASIO_WINDOWS)
+ std::cerr << "(You may need to run this program as root.)" << std::endl;
+#endif
+ return 1;
+ }
+
+ boost::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/src/boost/libs/asio/example/cpp03/invocation/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/invocation/Jamfile.v2
new file mode 100644
index 000000000..56beb37f0
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/invocation/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe prioritised_handlers
+ : prioritised_handlers.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/invocation/prioritised_handlers.cpp b/src/boost/libs/asio/example/cpp03/invocation/prioritised_handlers.cpp
new file mode 100644
index 000000000..f0d201d83
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/invocation/prioritised_handlers.cpp
@@ -0,0 +1,171 @@
+//
+// prioritised_handlers.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/function.hpp>
+#include <iostream>
+#include <queue>
+
+using boost::asio::ip::tcp;
+
+class handler_priority_queue : public boost::asio::execution_context
+{
+public:
+ void add(int priority, boost::function<void()> function)
+ {
+ handlers_.push(queued_handler(priority, function));
+ }
+
+ void execute_all()
+ {
+ while (!handlers_.empty())
+ {
+ queued_handler handler = handlers_.top();
+ handler.execute();
+ handlers_.pop();
+ }
+ }
+
+ class executor
+ {
+ public:
+ executor(handler_priority_queue& q, int p)
+ : context_(q), priority_(p)
+ {
+ }
+
+ handler_priority_queue& context() const
+ {
+ return context_;
+ }
+
+ template <typename Function, typename Allocator>
+ void dispatch(const Function& f, const Allocator&) const
+ {
+ context_.add(priority_, f);
+ }
+
+ template <typename Function, typename Allocator>
+ void post(const Function& f, const Allocator&) const
+ {
+ context_.add(priority_, f);
+ }
+
+ template <typename Function, typename Allocator>
+ void defer(const Function& f, const Allocator&) const
+ {
+ context_.add(priority_, f);
+ }
+
+ void on_work_started() const {}
+ void on_work_finished() const {}
+
+ bool operator==(const executor& other) const
+ {
+ return &context_ == &other.context_ && priority_ == other.priority_;
+ }
+
+ bool operator!=(const executor& other) const
+ {
+ return !operator==(other);
+ }
+
+ private:
+ handler_priority_queue& context_;
+ int priority_;
+ };
+
+ template <typename Handler>
+ boost::asio::executor_binder<Handler, executor>
+ wrap(int priority, Handler handler)
+ {
+ return boost::asio::bind_executor(executor(*this, priority), handler);
+ }
+
+private:
+ class queued_handler
+ {
+ public:
+ queued_handler(int p, boost::function<void()> f)
+ : priority_(p), function_(f)
+ {
+ }
+
+ void execute()
+ {
+ function_();
+ }
+
+ friend bool operator<(const queued_handler& a,
+ const queued_handler& b)
+ {
+ return a.priority_ < b.priority_;
+ }
+
+ private:
+ int priority_;
+ boost::function<void()> function_;
+ };
+
+ std::priority_queue<queued_handler> handlers_;
+};
+
+//----------------------------------------------------------------------
+
+void high_priority_handler(const boost::system::error_code& /*ec*/)
+{
+ std::cout << "High priority handler\n";
+}
+
+void middle_priority_handler(const boost::system::error_code& /*ec*/)
+{
+ std::cout << "Middle priority handler\n";
+}
+
+void low_priority_handler()
+{
+ std::cout << "Low priority handler\n";
+}
+
+int main()
+{
+ boost::asio::io_context io_context;
+
+ handler_priority_queue pri_queue;
+
+ // Post a completion handler to be run immediately.
+ boost::asio::post(io_context, pri_queue.wrap(0, low_priority_handler));
+
+ // Start an asynchronous accept that will complete immediately.
+ tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 0);
+ tcp::acceptor acceptor(io_context, endpoint);
+ tcp::socket server_socket(io_context);
+ acceptor.async_accept(server_socket,
+ pri_queue.wrap(100, high_priority_handler));
+ tcp::socket client_socket(io_context);
+ client_socket.connect(acceptor.local_endpoint());
+
+ // Set a deadline timer to expire immediately.
+ boost::asio::steady_timer timer(io_context);
+ timer.expires_at(boost::asio::steady_timer::time_point::min());
+ timer.async_wait(pri_queue.wrap(42, middle_priority_handler));
+
+ while (io_context.run_one())
+ {
+ // The custom invocation hook adds the handlers to the priority queue
+ // rather than executing them from within the poll_one() call.
+ while (io_context.poll_one())
+ ;
+
+ pri_queue.execute_all();
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/iostreams/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/iostreams/Jamfile.v2
new file mode 100644
index 000000000..ece413e23
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/iostreams/Jamfile.v2
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe daytime_client : daytime_client.cpp ;
+exe daytime_server : daytime_server.cpp ;
+exe http_client : http_client.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/iostreams/daytime_client.cpp b/src/boost/libs/asio/example/cpp03/iostreams/daytime_client.cpp
new file mode 100644
index 000000000..7abd1115f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/iostreams/daytime_client.cpp
@@ -0,0 +1,44 @@
+//
+// daytime_client.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+
+using boost::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/src/boost/libs/asio/example/cpp03/iostreams/daytime_server.cpp b/src/boost/libs/asio/example/cpp03/iostreams/daytime_server.cpp
new file mode 100644
index 000000000..bcc0b1605
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/iostreams/daytime_server.cpp
@@ -0,0 +1,51 @@
+//
+// daytime_server.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+
+using boost::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
+ {
+ boost::asio::io_context io_context;
+
+ tcp::endpoint endpoint(tcp::v4(), 13);
+ tcp::acceptor acceptor(io_context, endpoint);
+
+ for (;;)
+ {
+ tcp::iostream stream;
+ boost::system::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/src/boost/libs/asio/example/cpp03/iostreams/http_client.cpp b/src/boost/libs/asio/example/cpp03/iostreams/http_client.cpp
new file mode 100644
index 000000000..bc5613a03
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/iostreams/http_client.cpp
@@ -0,0 +1,91 @@
+//
+// http_client.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/ip/tcp.hpp>
+
+using boost::asio::ip::tcp;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cout << "Usage: http_client <server> <path>\n";
+ std::cout << "Example:\n";
+ std::cout << " http_client www.boost.org /LICENSE_1_0.txt\n";
+ return 1;
+ }
+
+ boost::asio::ip::tcp::iostream s;
+
+ // The entire sequence of I/O operations must complete within 60 seconds.
+ // If an expiry occurs, the socket is automatically closed and the stream
+ // becomes bad.
+ s.expires_after(boost::asio::chrono::seconds(60));
+
+ // Establish a connection to the server.
+ s.connect(argv[1], "http");
+ if (!s)
+ {
+ std::cout << "Unable to connect: " << s.error().message() << "\n";
+ return 1;
+ }
+
+ // Send 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.
+ s << "GET " << argv[2] << " HTTP/1.0\r\n";
+ s << "Host: " << argv[1] << "\r\n";
+ s << "Accept: */*\r\n";
+ s << "Connection: close\r\n\r\n";
+
+ // By default, the stream is tied with itself. This means that the stream
+ // automatically flush the buffered output before attempting a read. It is
+ // not necessary not explicitly flush the stream at this point.
+
+ // Check that response is OK.
+ std::string http_version;
+ s >> http_version;
+ unsigned int status_code;
+ s >> status_code;
+ std::string status_message;
+ std::getline(s, status_message);
+ if (!s || 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;
+ }
+
+ // Process the response headers, which are terminated by a blank line.
+ std::string header;
+ while (std::getline(s, header) && header != "\r")
+ std::cout << header << "\n";
+ std::cout << "\n";
+
+ // Write the remaining data to output.
+ std::cout << s.rdbuf();
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/local/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/local/Jamfile.v2
new file mode 100644
index 000000000..05ef40b90
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/local/Jamfile.v2
@@ -0,0 +1,82 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe connect_pair
+ : connect_pair.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ /boost/thread//boost_thread
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe iostream_client
+ : iostream_client.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe stream_client
+ : stream_client.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe stream_server
+ : stream_server.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/local/connect_pair.cpp b/src/boost/libs/asio/example/cpp03/local/connect_pair.cpp
new file mode 100644
index 000000000..7901783b6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/local/connect_pair.cpp
@@ -0,0 +1,142 @@
+//
+// connect_pair.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cctype>
+#include <boost/asio.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+
+using boost::asio::local::stream_protocol;
+
+class uppercase_filter
+{
+public:
+ uppercase_filter(boost::asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ stream_protocol::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ // Wait for request.
+ socket_.async_read_some(boost::asio::buffer(data_),
+ boost::bind(&uppercase_filter::handle_read,
+ this, boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+private:
+ void handle_read(const boost::system::error_code& ec, std::size_t size)
+ {
+ if (!ec)
+ {
+ // Compute result.
+ for (std::size_t i = 0; i < size; ++i)
+ data_[i] = std::toupper(data_[i]);
+
+ // Send result.
+ boost::asio::async_write(socket_, boost::asio::buffer(data_, size),
+ boost::bind(&uppercase_filter::handle_write,
+ this, boost::asio::placeholders::error));
+ }
+ else
+ {
+ throw boost::system::system_error(ec);
+ }
+ }
+
+ void handle_write(const boost::system::error_code& ec)
+ {
+ if (!ec)
+ {
+ // Wait for request.
+ socket_.async_read_some(boost::asio::buffer(data_),
+ boost::bind(&uppercase_filter::handle_read,
+ this, boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ throw boost::system::system_error(ec);
+ }
+ }
+
+ stream_protocol::socket socket_;
+ boost::array<char, 512> data_;
+};
+
+void run(boost::asio::io_context* io_context)
+{
+ try
+ {
+ io_context->run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception in thread: " << e.what() << "\n";
+ std::exit(1);
+ }
+}
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context;
+
+ // Create filter and establish a connection to it.
+ uppercase_filter filter(io_context);
+ stream_protocol::socket socket(io_context);
+ boost::asio::local::connect_pair(socket, filter.socket());
+ filter.start();
+
+ // The io_context runs in a background thread to perform filtering.
+ boost::thread thread(boost::bind(run, &io_context));
+
+ for (;;)
+ {
+ // Collect request from user.
+ std::cout << "Enter a string: ";
+ std::string request;
+ std::getline(std::cin, request);
+
+ // Send request to filter.
+ boost::asio::write(socket, boost::asio::buffer(request));
+
+ // Wait for reply from filter.
+ std::vector<char> reply(request.size());
+ boost::asio::read(socket, boost::asio::buffer(reply));
+
+ // Show reply to user.
+ std::cout << "Result: ";
+ std::cout.write(&reply[0], request.size());
+ std::cout << std::endl;
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ std::exit(1);
+ }
+}
+
+#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+# error Local sockets not available on this platform.
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
diff --git a/src/boost/libs/asio/example/cpp03/local/iostream_client.cpp b/src/boost/libs/asio/example/cpp03/local/iostream_client.cpp
new file mode 100644
index 000000000..4e61abb47
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/local/iostream_client.cpp
@@ -0,0 +1,62 @@
+//
+// stream_client.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstring>
+#include <iostream>
+#include <boost/asio.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+
+using boost::asio::local::stream_protocol;
+
+enum { max_length = 1024 };
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: iostream_client <file>\n";
+ return 1;
+ }
+
+ stream_protocol::endpoint ep(argv[1]);
+ stream_protocol::iostream s(ep);
+ if (!s)
+ {
+ std::cerr << "Unable to connect: " << s.error().message() << std::endl;
+ return 1;
+ }
+
+ using namespace std; // For strlen.
+ std::cout << "Enter message: ";
+ char request[max_length];
+ std::cin.getline(request, max_length);
+ size_t length = strlen(request);
+ s << request;
+
+ char reply[max_length];
+ s.read(reply, length);
+ std::cout << "Reply is: ";
+ std::cout.write(reply, length);
+ std::cout << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
+
+#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+# error Local sockets not available on this platform.
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
diff --git a/src/boost/libs/asio/example/cpp03/local/stream_client.cpp b/src/boost/libs/asio/example/cpp03/local/stream_client.cpp
new file mode 100644
index 000000000..2a62bdee2
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/local/stream_client.cpp
@@ -0,0 +1,61 @@
+//
+// stream_client.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <boost/asio.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+
+using boost::asio::local::stream_protocol;
+
+enum { max_length = 1024 };
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: stream_client <file>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ stream_protocol::socket s(io_context);
+ s.connect(stream_protocol::endpoint(argv[1]));
+
+ using namespace std; // For strlen.
+ std::cout << "Enter message: ";
+ char request[max_length];
+ std::cin.getline(request, max_length);
+ size_t request_length = strlen(request);
+ boost::asio::write(s, boost::asio::buffer(request, request_length));
+
+ char reply[max_length];
+ size_t reply_length = boost::asio::read(s,
+ boost::asio::buffer(reply, request_length));
+ std::cout << "Reply is: ";
+ std::cout.write(reply, reply_length);
+ std::cout << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
+
+#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+# error Local sockets not available on this platform.
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
diff --git a/src/boost/libs/asio/example/cpp03/local/stream_server.cpp b/src/boost/libs/asio/example/cpp03/local/stream_server.cpp
new file mode 100644
index 000000000..7d309ef2a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/local/stream_server.cpp
@@ -0,0 +1,141 @@
+//
+// stream_server.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdio>
+#include <iostream>
+#include <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/asio.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+
+using boost::asio::local::stream_protocol;
+
+class session
+ : public boost::enable_shared_from_this<session>
+{
+public:
+ session(boost::asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ stream_protocol::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ socket_.async_read_some(boost::asio::buffer(data_),
+ boost::bind(&session::handle_read,
+ shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+ void handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(data_, bytes_transferred),
+ boost::bind(&session::handle_write,
+ shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ socket_.async_read_some(boost::asio::buffer(data_),
+ boost::bind(&session::handle_read,
+ shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ }
+
+private:
+ // The socket used to communicate with the client.
+ stream_protocol::socket socket_;
+
+ // Buffer used to store data received from the client.
+ boost::array<char, 1024> data_;
+};
+
+typedef boost::shared_ptr<session> session_ptr;
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, const std::string& file)
+ : io_context_(io_context),
+ acceptor_(io_context, stream_protocol::endpoint(file))
+ {
+ session_ptr new_session(new session(io_context_));
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(session_ptr new_session,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_session->start();
+ }
+
+ new_session.reset(new session(io_context_));
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ stream_protocol::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: stream_server <file>\n";
+ std::cerr << "*** WARNING: existing file is removed ***\n";
+ return 1;
+ }
+
+ boost::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(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+# error Local sockets not available on this platform.
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
diff --git a/src/boost/libs/asio/example/cpp03/multicast/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/multicast/Jamfile.v2
new file mode 100644
index 000000000..909903a79
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/multicast/Jamfile.v2
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe receiver : receiver.cpp ;
+exe sender : sender.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/multicast/receiver.cpp b/src/boost/libs/asio/example/cpp03/multicast/receiver.cpp
new file mode 100644
index 000000000..f6da0138d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/multicast/receiver.cpp
@@ -0,0 +1,93 @@
+//
+// receiver.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include "boost/bind/bind.hpp"
+
+const short multicast_port = 30001;
+
+class receiver
+{
+public:
+ receiver(boost::asio::io_context& io_context,
+ const boost::asio::ip::address& listen_address,
+ const boost::asio::ip::address& multicast_address)
+ : socket_(io_context)
+ {
+ // Create the socket so that multiple may be bound to the same address.
+ boost::asio::ip::udp::endpoint listen_endpoint(
+ listen_address, multicast_port);
+ socket_.open(listen_endpoint.protocol());
+ socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
+ socket_.bind(listen_endpoint);
+
+ // Join the multicast group.
+ socket_.set_option(
+ boost::asio::ip::multicast::join_group(multicast_address));
+
+ socket_.async_receive_from(
+ boost::asio::buffer(data_, max_length), sender_endpoint_,
+ boost::bind(&receiver::handle_receive_from, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+ void handle_receive_from(const boost::system::error_code& error,
+ size_t bytes_recvd)
+ {
+ if (!error)
+ {
+ std::cout.write(data_, bytes_recvd);
+ std::cout << std::endl;
+
+ socket_.async_receive_from(
+ boost::asio::buffer(data_, max_length), sender_endpoint_,
+ boost::bind(&receiver::handle_receive_from, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ }
+
+private:
+ boost::asio::ip::udp::socket socket_;
+ boost::asio::ip::udp::endpoint sender_endpoint_;
+ enum { max_length = 1024 };
+ char data_[max_length];
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: receiver <listen_address> <multicast_address>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " receiver 0.0.0.0 239.255.0.1\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " receiver 0::0 ff31::8000:1234\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+ receiver r(io_context,
+ boost::asio::ip::make_address(argv[1]),
+ boost::asio::ip::make_address(argv[2]));
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/multicast/sender.cpp b/src/boost/libs/asio/example/cpp03/multicast/sender.cpp
new file mode 100644
index 000000000..256eb482f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/multicast/sender.cpp
@@ -0,0 +1,98 @@
+//
+// sender.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <sstream>
+#include <string>
+#include <boost/asio.hpp>
+#include "boost/bind/bind.hpp"
+
+const short multicast_port = 30001;
+const int max_message_count = 10;
+
+class sender
+{
+public:
+ sender(boost::asio::io_context& io_context,
+ const boost::asio::ip::address& multicast_address)
+ : endpoint_(multicast_address, multicast_port),
+ socket_(io_context, endpoint_.protocol()),
+ timer_(io_context),
+ message_count_(0)
+ {
+ std::ostringstream os;
+ os << "Message " << message_count_++;
+ message_ = os.str();
+
+ socket_.async_send_to(
+ boost::asio::buffer(message_), endpoint_,
+ boost::bind(&sender::handle_send_to, this,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_send_to(const boost::system::error_code& error)
+ {
+ if (!error && message_count_ < max_message_count)
+ {
+ timer_.expires_after(boost::asio::chrono::seconds(1));
+ timer_.async_wait(
+ boost::bind(&sender::handle_timeout, this,
+ boost::asio::placeholders::error));
+ }
+ }
+
+ void handle_timeout(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::ostringstream os;
+ os << "Message " << message_count_++;
+ message_ = os.str();
+
+ socket_.async_send_to(
+ boost::asio::buffer(message_), endpoint_,
+ boost::bind(&sender::handle_send_to, this,
+ boost::asio::placeholders::error));
+ }
+ }
+
+private:
+ boost::asio::ip::udp::endpoint endpoint_;
+ boost::asio::ip::udp::socket socket_;
+ boost::asio::steady_timer timer_;
+ int message_count_;
+ std::string message_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: sender <multicast_address>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " sender 239.255.0.1\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " sender ff31::8000:1234\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+ sender s(io_context, boost::asio::ip::make_address(argv[1]));
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/nonblocking/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/nonblocking/Jamfile.v2
new file mode 100644
index 000000000..0c4c30bae
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/nonblocking/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe third_party_lib
+ : third_party_lib.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/nonblocking/third_party_lib.cpp b/src/boost/libs/asio/example/cpp03/nonblocking/third_party_lib.cpp
new file mode 100644
index 000000000..86b11c6dd
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/nonblocking/third_party_lib.cpp
@@ -0,0 +1,240 @@
+//
+// third_party_lib.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <iostream>
+
+using boost::asio::ip::tcp;
+
+namespace third_party_lib {
+
+// Simulation of a third party library that wants to perform read and write
+// operations directly on a socket. It needs to be polled to determine whether
+// it requires a read or write operation, and notified when the socket is ready
+// for reading or writing.
+class session
+{
+public:
+ session(tcp::socket& socket)
+ : socket_(socket),
+ state_(reading)
+ {
+ }
+
+ // Returns true if the third party library wants to be notified when the
+ // socket is ready for reading.
+ bool want_read() const
+ {
+ return state_ == reading;
+ }
+
+ // Notify that third party library that it should perform its read operation.
+ void do_read(boost::system::error_code& ec)
+ {
+ if (std::size_t len = socket_.read_some(boost::asio::buffer(data_), ec))
+ {
+ write_buffer_ = boost::asio::buffer(data_, len);
+ state_ = writing;
+ }
+ }
+
+ // Returns true if the third party library wants to be notified when the
+ // socket is ready for writing.
+ bool want_write() const
+ {
+ return state_ == writing;
+ }
+
+ // Notify that third party library that it should perform its write operation.
+ void do_write(boost::system::error_code& ec)
+ {
+ if (std::size_t len = socket_.write_some(
+ boost::asio::buffer(write_buffer_), ec))
+ {
+ write_buffer_ = write_buffer_ + len;
+ state_ = boost::asio::buffer_size(write_buffer_) > 0 ? writing : reading;
+ }
+ }
+
+private:
+ tcp::socket& socket_;
+ enum { reading, writing } state_;
+ boost::array<char, 128> data_;
+ boost::asio::const_buffer write_buffer_;
+};
+
+} // namespace third_party_lib
+
+// The glue between asio's sockets and the third party library.
+class connection
+ : public boost::enable_shared_from_this<connection>
+{
+public:
+ typedef boost::shared_ptr<connection> pointer;
+
+ static pointer create(const boost::asio::executor& ex)
+ {
+ return pointer(new connection(ex));
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ // Put the socket into non-blocking mode.
+ socket_.non_blocking(true);
+
+ start_operations();
+ }
+
+private:
+ connection(const boost::asio::executor& ex)
+ : socket_(ex),
+ session_impl_(socket_),
+ read_in_progress_(false),
+ write_in_progress_(false)
+ {
+ }
+
+ void start_operations()
+ {
+ // Start a read operation if the third party library wants one.
+ if (session_impl_.want_read() && !read_in_progress_)
+ {
+ read_in_progress_ = true;
+ socket_.async_wait(tcp::socket::wait_read,
+ boost::bind(&connection::handle_read,
+ shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+
+ // Start a write operation if the third party library wants one.
+ if (session_impl_.want_write() && !write_in_progress_)
+ {
+ write_in_progress_ = true;
+ socket_.async_wait(tcp::socket::wait_write,
+ boost::bind(&connection::handle_write,
+ shared_from_this(),
+ boost::asio::placeholders::error));
+ }
+ }
+
+ void handle_read(boost::system::error_code ec)
+ {
+ read_in_progress_ = false;
+
+ // Notify third party library that it can perform a read.
+ if (!ec)
+ session_impl_.do_read(ec);
+
+ // The third party library successfully performed a read on the socket.
+ // Start new read or write operations based on what it now wants.
+ if (!ec || ec == boost::asio::error::would_block)
+ start_operations();
+
+ // Otherwise, an error occurred. Closing the socket cancels any outstanding
+ // asynchronous read or write operations. The connection object will be
+ // destroyed automatically once those outstanding operations complete.
+ else
+ socket_.close();
+ }
+
+ void handle_write(boost::system::error_code ec)
+ {
+ write_in_progress_ = false;
+
+ // Notify third party library that it can perform a write.
+ if (!ec)
+ session_impl_.do_write(ec);
+
+ // The third party library successfully performed a write on the socket.
+ // Start new read or write operations based on what it now wants.
+ if (!ec || ec == boost::asio::error::would_block)
+ start_operations();
+
+ // Otherwise, an error occurred. Closing the socket cancels any outstanding
+ // asynchronous read or write operations. The connection object will be
+ // destroyed automatically once those outstanding operations complete.
+ else
+ socket_.close();
+ }
+
+private:
+ tcp::socket socket_;
+ third_party_lib::session session_impl_;
+ bool read_in_progress_;
+ bool write_in_progress_;
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, unsigned short port)
+ : acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
+ {
+ start_accept();
+ }
+
+private:
+ void start_accept()
+ {
+ connection::pointer new_connection =
+ connection::create(acceptor_.get_executor());
+
+ acceptor_.async_accept(new_connection->socket(),
+ boost::bind(&server::handle_accept, this, new_connection,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(connection::pointer new_connection,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_connection->start();
+ }
+
+ start_accept();
+ }
+
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: third_party_lib <port>\n";
+ return 1;
+ }
+
+ boost::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() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/porthopper/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/porthopper/Jamfile.v2
new file mode 100644
index 000000000..64d070c28
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/porthopper/Jamfile.v2
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe client : client.cpp ;
+exe server : server.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/porthopper/client.cpp b/src/boost/libs/asio/example/cpp03/porthopper/client.cpp
new file mode 100644
index 000000000..fc258515d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/porthopper/client.cpp
@@ -0,0 +1,192 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/if.hpp>
+#include <boost/shared_ptr.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <exception>
+#include <iostream>
+#include <string>
+#include "protocol.hpp"
+
+using namespace boost;
+using boost::asio::ip::tcp;
+using boost::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];
+
+ boost::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.
+ boost::shared_ptr<udp::socket> data_socket(
+ new udp::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());
+ boost::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.
+ boost::shared_ptr<udp::socket> new_data_socket(
+ new udp::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());
+ boost::system::error_code control_result;
+ boost::asio::async_write(control_socket, change.to_buffers(),
+ (
+ lambda::var(control_result) = lambda::_1
+ ));
+
+ // 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;
+ boost::system::error_code new_data_socket_result;
+ new_data_socket->async_receive(f1.to_buffers(),
+ (
+ // Note: lambda::_1 is the first argument to the callback handler,
+ // which in this case is the error code for the operation.
+ lambda::var(new_data_socket_result) = lambda::_1,
+ lambda::if_(!lambda::_1)
+ [
+ // 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.
+ lambda::var(data_socket) = boost::shared_ptr<udp::socket>()
+ ]
+ ));
+
+ // 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) // Might have been closed by new_data_socket's handler.
+ {
+ data_socket->async_receive(f2.to_buffers(), 0,
+ (
+ lambda::if_(!lambda::_1)
+ [
+ // We have successfully received a frame on the old data
+ // socket. Stop the io_context so that we can print it.
+ lambda::bind(&boost::asio::io_context::stop, &io_context),
+ lambda::var(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 boost::system::system_error(control_result);
+ if (new_data_socket_result)
+ throw boost::system::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 = 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/src/boost/libs/asio/example/cpp03/porthopper/protocol.hpp b/src/boost/libs/asio/example/cpp03/porthopper/protocol.hpp
new file mode 100644
index 000000000..38e2ee896
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/porthopper/protocol.hpp
@@ -0,0 +1,156 @@
+//
+// protocol.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/array.hpp>
+#include <boost/asio.hpp>
+#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.
+ boost::array<boost::asio::mutable_buffer, 1> to_buffers()
+ {
+ boost::array<boost::asio::mutable_buffer, 1> buffers
+ = { { boost::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.
+ boost::array<boost::asio::mutable_buffer, 1> to_buffers()
+ {
+ boost::array<boost::asio::mutable_buffer, 1> buffers
+ = { { boost::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/src/boost/libs/asio/example/cpp03/porthopper/server.cpp b/src/boost/libs/asio/example/cpp03/porthopper/server.cpp
new file mode 100644
index 000000000..191f62088
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/porthopper/server.cpp
@@ -0,0 +1,187 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <cmath>
+#include <cstdlib>
+#include <exception>
+#include <iostream>
+#include <set>
+#include "protocol.hpp"
+
+using boost::asio::ip::tcp;
+using boost::asio::ip::udp;
+
+typedef boost::shared_ptr<tcp::socket> tcp_socket_ptr;
+typedef boost::shared_ptr<boost::asio::steady_timer> timer_ptr;
+typedef boost::shared_ptr<control_request> control_request_ptr;
+
+class server
+{
+public:
+ // Construct the server to wait for incoming control connections.
+ server(boost::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,
+ boost::bind(&server::handle_accept, this,
+ boost::asio::placeholders::error, new_socket));
+
+ // Start the timer used to generate outgoing frames.
+ timer_.expires_after(boost::asio::chrono::milliseconds(100));
+ timer_.async_wait(boost::bind(&server::handle_timer, this));
+ }
+
+ // Handle a new control connection.
+ void handle_accept(const boost::system::error_code& ec, tcp_socket_ptr socket)
+ {
+ if (!ec)
+ {
+ // Start receiving control requests on the connection.
+ control_request_ptr request(new control_request);
+ boost::asio::async_read(*socket, request->to_buffers(),
+ boost::bind(&server::handle_control_request, this,
+ boost::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,
+ boost::bind(&server::handle_accept, this,
+ boost::asio::placeholders::error, new_socket));
+ }
+
+ // Handle a new control request.
+ void handle_control_request(const boost::system::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 boost::asio::steady_timer(acceptor_.get_executor()));
+ delay_timer->expires_after(boost::asio::chrono::seconds(2));
+ delay_timer->async_wait(
+ boost::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.
+ boost::system::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.
+ boost::asio::async_read(*socket, request->to_buffers(),
+ boost::bind(&server::handle_control_request, this,
+ boost::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)
+ {
+ boost::system::error_code ec;
+ udp_socket_.send_to(f.to_buffers(), *j, 0, ec);
+ }
+
+ // Wait for next timeout.
+ timer_.expires_after(boost::asio::chrono::milliseconds(100));
+ timer_.async_wait(boost::bind(&server::handle_timer, this));
+ }
+
+private:
+ // The acceptor used to accept incoming control connections.
+ tcp::acceptor acceptor_;
+
+ // The timer used for generating data.
+ boost::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;
+ }
+
+ boost::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/src/boost/libs/asio/example/cpp03/serialization/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/serialization/Jamfile.v2
new file mode 100644
index 000000000..c0231b8b7
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/serialization/Jamfile.v2
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe client : client.cpp ;
+exe server : server.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/serialization/client.cpp b/src/boost/libs/asio/example/cpp03/serialization/client.cpp
new file mode 100644
index 000000000..f4b9b8efd
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/serialization/client.cpp
@@ -0,0 +1,125 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#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(boost::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.
+ boost::asio::ip::tcp::resolver resolver(io_context);
+ boost::asio::ip::tcp::resolver::query query(host, service);
+ boost::asio::ip::tcp::resolver::iterator endpoint_iterator =
+ resolver.resolve(query);
+
+ // Start an asynchronous connect operation.
+ boost::asio::async_connect(connection_.socket(), endpoint_iterator,
+ boost::bind(&client::handle_connect, this,
+ boost::asio::placeholders::error));
+ }
+
+ /// Handle completion of a connect operation.
+ void handle_connect(const boost::system::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_,
+ boost::bind(&client::handle_read, this,
+ boost::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 boost::system::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;
+ }
+
+ boost::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/src/boost/libs/asio/example/cpp03/serialization/connection.hpp b/src/boost/libs/asio/example/cpp03/serialization/connection.hpp
new file mode 100644
index 000000000..e6801614d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/serialization/connection.hpp
@@ -0,0 +1,188 @@
+//
+// connection.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#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 boost::asio::executor& ex)
+ : socket_(ex)
+ {
+ }
+
+ /// Get the underlying socket. Used for making a connection or for accepting
+ /// an incoming connection.
+ boost::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.
+ boost::system::error_code error(boost::asio::error::invalid_argument);
+ boost::asio::post(socket_.get_executor(), boost::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<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(outbound_header_));
+ buffers.push_back(boost::asio::buffer(outbound_data_));
+ boost::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 boost::system::error_code&,
+ T&, boost::tuple<Handler>)
+ = &connection::handle_read_header<T, Handler>;
+ boost::asio::async_read(socket_, boost::asio::buffer(inbound_header_),
+ boost::bind(f,
+ this, boost::asio::placeholders::error, boost::ref(t),
+ boost::make_tuple(handler)));
+ }
+
+ /// Handle a completed read of a message header. The handler is passed using
+ /// a tuple since boost::bind seems to have trouble binding a function object
+ /// created using boost::bind as a parameter.
+ template <typename T, typename Handler>
+ void handle_read_header(const boost::system::error_code& e,
+ T& t, boost::tuple<Handler> handler)
+ {
+ if (e)
+ {
+ boost::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.
+ boost::system::error_code error(boost::asio::error::invalid_argument);
+ boost::get<0>(handler)(error);
+ return;
+ }
+
+ // Start an asynchronous call to receive the data.
+ inbound_data_.resize(inbound_data_size);
+ void (connection::*f)(
+ const boost::system::error_code&,
+ T&, boost::tuple<Handler>)
+ = &connection::handle_read_data<T, Handler>;
+ boost::asio::async_read(socket_, boost::asio::buffer(inbound_data_),
+ boost::bind(f, this,
+ boost::asio::placeholders::error, boost::ref(t), handler));
+ }
+ }
+
+ /// Handle a completed read of message data.
+ template <typename T, typename Handler>
+ void handle_read_data(const boost::system::error_code& e,
+ T& t, boost::tuple<Handler> handler)
+ {
+ if (e)
+ {
+ boost::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.
+ boost::system::error_code error(boost::asio::error::invalid_argument);
+ boost::get<0>(handler)(error);
+ return;
+ }
+
+ // Inform caller that data has been received ok.
+ boost::get<0>(handler)(e);
+ }
+ }
+
+private:
+ /// The underlying socket.
+ boost::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 boost::shared_ptr<connection> connection_ptr;
+
+} // namespace s11n_example
+
+#endif // SERIALIZATION_CONNECTION_HPP
diff --git a/src/boost/libs/asio/example/cpp03/serialization/server.cpp b/src/boost/libs/asio/example/cpp03/serialization/server.cpp
new file mode 100644
index 000000000..4e527cf27
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/serialization/server.cpp
@@ -0,0 +1,123 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/lexical_cast.hpp>
+#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(boost::asio::io_context& io_context, unsigned short port)
+ : acceptor_(io_context,
+ boost::asio::ip::tcp::endpoint(boost::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(),
+ boost::bind(&server::handle_accept, this,
+ boost::asio::placeholders::error, new_conn));
+ }
+
+ /// Handle completion of a accept operation.
+ void handle_accept(const boost::system::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_,
+ boost::bind(&server::handle_write, this,
+ boost::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(),
+ boost::bind(&server::handle_accept, this,
+ boost::asio::placeholders::error, new_conn));
+ }
+
+ /// Handle completion of a write operation.
+ void handle_write(const boost::system::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.
+ boost::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 = boost::lexical_cast<unsigned short>(argv[1]);
+
+ boost::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/src/boost/libs/asio/example/cpp03/serialization/stock.hpp b/src/boost/libs/asio/example/cpp03/serialization/stock.hpp
new file mode 100644
index 000000000..ca5a1c957
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/serialization/stock.hpp
@@ -0,0 +1,50 @@
+//
+// stock.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/services/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/services/Jamfile.v2
new file mode 100644
index 000000000..3a2634d74
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/services/Jamfile.v2
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe daytime_client
+ : daytime_client.cpp
+ logger_service.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ /boost/thread//boost_thread
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/services/basic_logger.hpp b/src/boost/libs/asio/example/cpp03/services/basic_logger.hpp
new file mode 100644
index 000000000..d7cc42579
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/services/basic_logger.hpp
@@ -0,0 +1,83 @@
+//
+// basic_logger.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/noncopyable.hpp>
+#include <string>
+
+namespace services {
+
+/// Class to provide simple logging functionality. Use the services::logger
+/// typedef.
+template <typename Service>
+class basic_logger
+ : private boost::noncopyable
+{
+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(boost::asio::execution_context& context,
+ const std::string& identifier)
+ : service_(boost::asio::use_service<Service>(context)),
+ impl_(service_.null())
+ {
+ service_.create(impl_, identifier);
+ }
+
+ /// Destructor.
+ ~basic_logger()
+ {
+ service_.destroy(impl_);
+ }
+
+ /// Get the io_context associated with the object.
+ boost::asio::io_context& get_io_context()
+ {
+ return service_.get_io_context();
+ }
+
+ /// 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/src/boost/libs/asio/example/cpp03/services/daytime_client.cpp b/src/boost/libs/asio/example/cpp03/services/daytime_client.cpp
new file mode 100644
index 000000000..59a0a6269
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/services/daytime_client.cpp
@@ -0,0 +1,97 @@
+//
+// daytime_client.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include <iostream>
+#include "logger.hpp"
+
+using boost::asio::ip::tcp;
+
+char read_buffer[1024];
+
+void read_handler(const boost::system::error_code& e,
+ std::size_t bytes_transferred, tcp::socket* s)
+{
+ if (!e)
+ {
+ std::cout.write(read_buffer, bytes_transferred);
+
+ s->async_read_some(boost::asio::buffer(read_buffer),
+ boost::bind(read_handler, boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred, s));
+ }
+ else
+ {
+ services::logger logger(s->get_executor().context(), "read_handler");
+
+ std::string msg = "Read error: ";
+ msg += e.message();
+ logger.log(msg);
+ }
+}
+
+void connect_handler(const boost::system::error_code& e, tcp::socket* s)
+{
+ services::logger logger(s->get_executor().context(), "connect_handler");
+
+ if (!e)
+ {
+ logger.log("Connection established");
+
+ s->async_read_some(boost::asio::buffer(read_buffer),
+ boost::bind(read_handler, boost::asio::placeholders::error,
+ boost::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;
+ }
+
+ boost::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);
+ boost::asio::async_connect(socket, endpoints,
+ boost::bind(connect_handler,
+ boost::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/src/boost/libs/asio/example/cpp03/services/logger.hpp b/src/boost/libs/asio/example/cpp03/services/logger.hpp
new file mode 100644
index 000000000..4eb00268a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/services/logger.hpp
@@ -0,0 +1,24 @@
+//
+// logger.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/services/logger_service.cpp b/src/boost/libs/asio/example/cpp03/services/logger_service.cpp
new file mode 100644
index 000000000..c1c9ac4e5
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/services/logger_service.cpp
@@ -0,0 +1,11 @@
+//
+// logger_service.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/services/logger_service.hpp b/src/boost/libs/asio/example/cpp03/services/logger_service.hpp
new file mode 100644
index 000000000..4f439c5e1
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/services/logger_service.hpp
@@ -0,0 +1,146 @@
+//
+// logger_service.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+namespace services {
+
+/// Service implementation for the logger.
+class logger_service
+ : public boost::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(boost::asio::execution_context& context)
+ : boost::asio::execution_context::service(context),
+ work_io_context_(),
+ work_(boost::asio::make_work_guard(work_io_context_)),
+ work_thread_(new boost::thread(
+ boost::bind(&boost::asio::io_context::run, &work_io_context_)))
+ {
+ }
+
+ /// 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_)
+ 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.
+ boost::asio::post(work_io_context_, boost::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.
+ boost::asio::post(work_io_context_, boost::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.
+ boost::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.
+ boost::asio::executor_work_guard<
+ boost::asio::io_context::executor_type> work_;
+
+ /// Thread used for running the work io_context's run loop.
+ boost::scoped_ptr<boost::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/src/boost/libs/asio/example/cpp03/socks4/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/socks4/Jamfile.v2
new file mode 100644
index 000000000..aa1492bad
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/socks4/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : sync_client.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/socks4/socks4.hpp b/src/boost/libs/asio/example/cpp03/socks4/socks4.hpp
new file mode 100644
index 000000000..ad72b120f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/socks4/socks4.hpp
@@ -0,0 +1,144 @@
+//
+// socks4.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 SOCKS4_HPP
+#define SOCKS4_HPP
+
+#include <string>
+#include <boost/asio.hpp>
+#include <boost/array.hpp>
+
+namespace socks4 {
+
+const unsigned char version = 0x04;
+
+class request
+{
+public:
+ enum command_type
+ {
+ connect = 0x01,
+ bind = 0x02
+ };
+
+ request(command_type cmd, const boost::asio::ip::tcp::endpoint& endpoint,
+ const std::string& user_id)
+ : version_(version),
+ command_(cmd),
+ user_id_(user_id),
+ null_byte_(0)
+ {
+ // Only IPv4 is supported by the SOCKS 4 protocol.
+ if (endpoint.protocol() != boost::asio::ip::tcp::v4())
+ {
+ throw boost::system::system_error(
+ boost::asio::error::address_family_not_supported);
+ }
+
+ // Convert port number to network byte order.
+ unsigned short port = endpoint.port();
+ port_high_byte_ = (port >> 8) & 0xff;
+ port_low_byte_ = port & 0xff;
+
+ // Save IP address in network byte order.
+ address_ = endpoint.address().to_v4().to_bytes();
+ }
+
+ boost::array<boost::asio::const_buffer, 7> buffers() const
+ {
+ boost::array<boost::asio::const_buffer, 7> bufs =
+ {
+ {
+ boost::asio::buffer(&version_, 1),
+ boost::asio::buffer(&command_, 1),
+ boost::asio::buffer(&port_high_byte_, 1),
+ boost::asio::buffer(&port_low_byte_, 1),
+ boost::asio::buffer(address_),
+ boost::asio::buffer(user_id_),
+ boost::asio::buffer(&null_byte_, 1)
+ }
+ };
+ return bufs;
+ }
+
+private:
+ unsigned char version_;
+ unsigned char command_;
+ unsigned char port_high_byte_;
+ unsigned char port_low_byte_;
+ boost::asio::ip::address_v4::bytes_type address_;
+ std::string user_id_;
+ unsigned char null_byte_;
+};
+
+class reply
+{
+public:
+ enum status_type
+ {
+ request_granted = 0x5a,
+ request_failed = 0x5b,
+ request_failed_no_identd = 0x5c,
+ request_failed_bad_user_id = 0x5d
+ };
+
+ reply()
+ : null_byte_(0),
+ status_()
+ {
+ }
+
+ boost::array<boost::asio::mutable_buffer, 5> buffers()
+ {
+ boost::array<boost::asio::mutable_buffer, 5> bufs =
+ {
+ {
+ boost::asio::buffer(&null_byte_, 1),
+ boost::asio::buffer(&status_, 1),
+ boost::asio::buffer(&port_high_byte_, 1),
+ boost::asio::buffer(&port_low_byte_, 1),
+ boost::asio::buffer(address_)
+ }
+ };
+ return bufs;
+ }
+
+ bool success() const
+ {
+ return null_byte_ == 0 && status_ == request_granted;
+ }
+
+ unsigned char status() const
+ {
+ return status_;
+ }
+
+ boost::asio::ip::tcp::endpoint endpoint() const
+ {
+ unsigned short port = port_high_byte_;
+ port = (port << 8) & 0xff00;
+ port = port | port_low_byte_;
+
+ boost::asio::ip::address_v4 address(address_);
+
+ return boost::asio::ip::tcp::endpoint(address, port);
+ }
+
+private:
+ unsigned char null_byte_;
+ unsigned char status_;
+ unsigned char port_high_byte_;
+ unsigned char port_low_byte_;
+ boost::asio::ip::address_v4::bytes_type address_;
+};
+
+} // namespace socks4
+
+#endif // SOCKS4_HPP
diff --git a/src/boost/libs/asio/example/cpp03/socks4/sync_client.cpp b/src/boost/libs/asio/example/cpp03/socks4/sync_client.cpp
new file mode 100644
index 000000000..a2edd89cd
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/socks4/sync_client.cpp
@@ -0,0 +1,94 @@
+//
+// sync_client.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <iomanip>
+#include <ostream>
+#include <string>
+#include <boost/asio.hpp>
+#include <boost/array.hpp>
+#include "socks4.hpp"
+
+using boost::asio::ip::tcp;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 4)
+ {
+ std::cout << "Usage: sync_client <socks4server> <socks4port> <user>\n";
+ std::cout << "Examples:\n";
+ std::cout << " sync_client 127.0.0.1 1080 chris\n";
+ std::cout << " sync_client localhost socks chris\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ // Get a list of endpoints corresponding to the SOCKS 4 server name.
+ tcp::resolver resolver(io_context);
+ tcp::resolver::results_type endpoints = resolver.resolve(argv[1], argv[2]);
+
+ // Try each endpoint until we successfully establish a connection to the
+ // SOCKS 4 server.
+ tcp::socket socket(io_context);
+ boost::asio::connect(socket, endpoints);
+
+ // Get an endpoint for the Boost website. This will be passed to the SOCKS
+ // 4 server. Explicitly specify IPv4 since SOCKS 4 does not support IPv6.
+ tcp::endpoint http_endpoint =
+ *resolver.resolve(tcp::v4(), "www.boost.org", "http").begin();
+
+ // Send the request to the SOCKS 4 server.
+ socks4::request socks_request(
+ socks4::request::connect, http_endpoint, argv[3]);
+ boost::asio::write(socket, socks_request.buffers());
+
+ // Receive a response from the SOCKS 4 server.
+ socks4::reply socks_reply;
+ boost::asio::read(socket, socks_reply.buffers());
+
+ // Check whether we successfully negotiated with the SOCKS 4 server.
+ if (!socks_reply.success())
+ {
+ std::cout << "Connection failed.\n";
+ std::cout << "status = 0x" << std::hex << socks_reply.status();
+ return 1;
+ }
+
+ // Form the HTTP 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 response.
+ std::string request =
+ "GET / HTTP/1.0\r\n"
+ "Host: www.boost.org\r\n"
+ "Accept: */*\r\n"
+ "Connection: close\r\n\r\n";
+
+ // Send the HTTP request.
+ boost::asio::write(socket, boost::asio::buffer(request));
+
+ // Read until EOF, writing data to output as we go.
+ boost::array<char, 512> response;
+ boost::system::error_code error;
+ while (std::size_t s = socket.read_some(
+ boost::asio::buffer(response), error))
+ std::cout.write(response.data(), s);
+ if (error != boost::asio::error::eof)
+ throw boost::system::system_error(error);
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/spawn/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/spawn/Jamfile.v2
new file mode 100644
index 000000000..7e4b320ef
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/spawn/Jamfile.v2
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : echo_server.cpp
+ /boost/context//boost_context
+ /boost/coroutine//boost_coroutine
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe parallel_grep
+ : parallel_grep.cpp
+ /boost/context//boost_context
+ /boost/coroutine//boost_coroutine
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/spawn/echo_server.cpp b/src/boost/libs/asio/example/cpp03/spawn/echo_server.cpp
new file mode 100644
index 000000000..9efe62b92
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/spawn/echo_server.cpp
@@ -0,0 +1,122 @@
+//
+// echo_server.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/spawn.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <iostream>
+
+using boost::asio::ip::tcp;
+
+class session : public boost::enable_shared_from_this<session>
+{
+public:
+ explicit session(boost::asio::io_context& io_context)
+ : strand_(boost::asio::make_strand(io_context)),
+ socket_(io_context),
+ timer_(io_context)
+ {
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void go()
+ {
+ boost::asio::spawn(strand_,
+ boost::bind(&session::echo,
+ shared_from_this(), boost::placeholders::_1));
+ boost::asio::spawn(strand_,
+ boost::bind(&session::timeout,
+ shared_from_this(), boost::placeholders::_1));
+ }
+
+private:
+ void echo(boost::asio::yield_context yield)
+ {
+ try
+ {
+ char data[128];
+ for (;;)
+ {
+ timer_.expires_after(boost::asio::chrono::seconds(10));
+ std::size_t n = socket_.async_read_some(boost::asio::buffer(data), yield);
+ boost::asio::async_write(socket_, boost::asio::buffer(data, n), yield);
+ }
+ }
+ catch (std::exception& e)
+ {
+ socket_.close();
+ timer_.cancel();
+ }
+ }
+
+ void timeout(boost::asio::yield_context yield)
+ {
+ while (socket_.is_open())
+ {
+ boost::system::error_code ignored_ec;
+ timer_.async_wait(yield[ignored_ec]);
+ if (timer_.expiry() <= boost::asio::steady_timer::clock_type::now())
+ socket_.close();
+ }
+ }
+
+ boost::asio::strand<boost::asio::io_context::executor_type> strand_;
+ tcp::socket socket_;
+ boost::asio::steady_timer timer_;
+};
+
+void do_accept(boost::asio::io_context& io_context,
+ unsigned short port, boost::asio::yield_context yield)
+{
+ tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));
+
+ for (;;)
+ {
+ boost::system::error_code ec;
+ boost::shared_ptr<session> new_session(new session(io_context));
+ acceptor.async_accept(new_session->socket(), yield[ec]);
+ if (!ec) new_session->go();
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ boost::asio::spawn(io_context,
+ boost::bind(do_accept,
+ boost::ref(io_context), atoi(argv[1]), boost::placeholders::_1));
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/spawn/parallel_grep.cpp b/src/boost/libs/asio/example/cpp03/spawn/parallel_grep.cpp
new file mode 100644
index 000000000..832b09ab6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/spawn/parallel_grep.cpp
@@ -0,0 +1,90 @@
+//
+// parallel_grep.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/dispatch.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/spawn.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/bind/bind.hpp>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+using boost::asio::dispatch;
+using boost::asio::spawn;
+using boost::asio::strand;
+using boost::asio::thread_pool;
+using boost::asio::yield_context;
+
+void print_match(std::string input_file, std::string line)
+{
+ std::cout << input_file << ':' << line << std::endl;
+}
+
+void search_file(std::string search_string, std::string input_file,
+ strand<thread_pool::executor_type> output_strand, yield_context yield)
+{
+ std::ifstream is(input_file.c_str());
+ std::string line;
+ std::size_t line_num = 0;
+ while (std::getline(is, line))
+ {
+ // If we find a match, send a message to the output.
+ if (line.find(search_string) != std::string::npos)
+ {
+ dispatch(output_strand, boost::bind(&print_match, input_file, line));
+ }
+
+ // Every so often we yield control to another coroutine.
+ if (++line_num % 10 == 0)
+ post(yield);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc < 2)
+ {
+ std::cerr << "Usage: parallel_grep <string> <files...>\n";
+ return 1;
+ }
+
+ // We use a fixed size pool of threads for reading the input files. The
+ // number of threads is automatically determined based on the number of
+ // CPUs available in the system.
+ thread_pool pool;
+
+ // To prevent the output from being garbled, we use a strand to synchronise
+ // printing.
+ strand<thread_pool::executor_type> output_strand(pool.get_executor());
+
+ // Spawn a new coroutine for each file specified on the command line.
+ std::string search_string = argv[1];
+ for (int argn = 2; argn < argc; ++argn)
+ {
+ std::string input_file = argv[argn];
+ spawn(pool, boost::bind(&search_file, search_string,
+ input_file, output_strand, boost::placeholders::_1));
+ }
+
+ // Join the thread pool to wait for all the spawned tasks to complete.
+ pool.join();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/ssl/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/ssl/Jamfile.v2
new file mode 100644
index 000000000..a7805abb8
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/ssl/Jamfile.v2
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+import os ;
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+if [ os.name ] = NT
+{
+ lib ssl : : <name>ssleay32 ;
+ lib crypto : : <name>libeay32 ;
+}
+else
+{
+ lib ssl ;
+ lib crypto ;
+}
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ <library>ssl
+ <library>crypto
+ ;
+
+exe client : client.cpp ;
+exe server : server.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/ssl/README b/src/boost/libs/asio/example/cpp03/ssl/README
new file mode 100644
index 000000000..7dea8cc9b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/ssl/README
@@ -0,0 +1,8 @@
+The passphrase for both the CA and server private keys is "test".
+
+
+-------------------------------------------------------------------------------
+Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp03/ssl/ca.pem b/src/boost/libs/asio/example/cpp03/ssl/ca.pem
new file mode 100644
index 000000000..1ee5f2ca4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/ssl/ca.pem
@@ -0,0 +1,49 @@
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIJAMJYU3U6A0IRMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
+BAYTAkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChME
+YXNpbzAeFw0xNTExMTgyMjMzNDhaFw0yMDExMTYyMjMzNDhaMDsxCzAJBgNVBAYT
+AkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChMEYXNp
+bzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcRJocHdVMdLUJ/pypY
+QVSTC0t3IIgjwjazrK3kAaoIMvzPmDFxEXWcDx+nyz8kQ/E38Ir/ef2BCNGci5hu
+wkfMSuMoW9l2N4hx3QCcF46tTDEZztFxWAH7QbE2wYMlMgKZSxWimNfq0YjxEEXb
+QM0lGPLFh7Xoko29H0F3LKaaQV9u/vop3Hs0h12HeWlY4PiLp7QQTNGqbWcXycA0
+NZ/fyismireyEvPAgo6L8iXuAi7g0TVKVNlrticGGjMcMq6IMvxzEpSMkuMQ5rWj
+pZjWOoBjSYBuXdblcBRvXhOr2Ws8jJLMZfehKq9q1reQfoGV6xMnbwmumSXbWRWT
+0vkCAwEAAaOBnTCBmjAdBgNVHQ4EFgQUK/Zv/AVtfIeucJw8VEtux1dhI1YwawYD
+VR0jBGQwYoAUK/Zv/AVtfIeucJw8VEtux1dhI1ahP6Q9MDsxCzAJBgNVBAYTAkFV
+MQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChMEYXNpb4IJ
+AMJYU3U6A0IRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABLYXimq
+v/HLyIJi7Xn8AJUsICj8LKF/J24nwwiF+ibf7UkoChJURs4nN78bod/lpDVPTEVl
+gTBdV/vBJs416sCEFfsGjqB9OBYj4gb0VaJDsQd0+NMvXp0faKv2y9wgScxG9/cg
+aM7eRmyfMn1qjb6tpNxVOPpe/nFi8Vx/1orejBRaZr4zF5TkoPepfwLWQeXDUIdE
++QHZ60jZAkR5RXTVU4u3kOKcJs839pmJYyxM4H2VxpR18vy4/YdIVWkREIUM2OgT
+5iznIQIIgR56QRGP85uef+I6n0BHzrBk6du69bkQFxrFjLVGlal4bIQqSg4KGWgx
+dEdymMWzmMxpO9s=
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEAxxEmhwd1Ux0tQn+nKlhBVJMLS3cgiCPCNrOsreQBqggy/M+Y
+MXERdZwPH6fLPyRD8Tfwiv95/YEI0ZyLmG7CR8xK4yhb2XY3iHHdAJwXjq1MMRnO
+0XFYAftBsTbBgyUyAplLFaKY1+rRiPEQRdtAzSUY8sWHteiSjb0fQXcspppBX27+
++incezSHXYd5aVjg+IuntBBM0aptZxfJwDQ1n9/KKyaKt7IS88CCjovyJe4CLuDR
+NUpU2Wu2JwYaMxwyrogy/HMSlIyS4xDmtaOlmNY6gGNJgG5d1uVwFG9eE6vZazyM
+ksxl96Eqr2rWt5B+gZXrEydvCa6ZJdtZFZPS+QIDAQABAoIBAQCOma+SvPoDzvvU
+DiPOxqgOEMPfjHfGbm86xl0luBalGfiEd6WbjVanfGKtF4MWOUFec+chez+FJMEP
+fufVC0qrKiJfNVMOpYvEd2SMgkSx1VymM8me6WXVDYsSipn2+1cm228ZEYAR9Emj
+oqQ4loaGLlP/3RaJbhBF7ruMJvXaZZQ4fZy74Z4tyRaaE1B659ua7Rjne7eNhQE8
+cR7cQDkxsNNN3LTbfLRwEc/gcDXWgLe5JlR/K4ZrdKc3lyivm+Uew3ubKs+fgkyY
+kHmuI3RJGIjpnsZW0/So+pHm3b/fo6lmlhTXtNNd+tkkKn2K9ttbXT3Sc13Pc+4w
+c4MLyUpdAoGBAOxTtGDpeF6U4s+GPuOCzHCwKQyzfOyCL/UTZv1UJX7Kn1FYycJH
+eOjtBRtS661cGkGd1MPfjdX2VV84AmBGDUmRqJ2KfTI1NjLAEJ115ANTpmSTm3lF
+UYncgbzl6aflLpjE1mgY+JTJykYeN5jhhO0r2bsdY7S+zaMCSI5NLuznAoGBANej
+aMtqLg2qKoq+fUkNBHHLXelR5dBXFnKgSrTj++H4yeW9pYbl8bK3gTF3I5+dSjHW
+DdC4+X09iPqY7p8vm8Gq/vgO8Bu+EnKNVr80PJSj7AzFGd6mk/CVrAzoY2XJWbAp
+YFwpo1WfHjS5wBfQzBlXY7kWVB7fj32kk14PYmUfAoGBAJXfd7NGHPoOfdCSGGv8
+VV7ZuQ6+/WiYH4XS6iuaI7VHFsZmAn3dCcbeGbD8Y04r7NLUH0yhB7g7YmTihk87
+3c1cPIy8eS1QJbEFsQPK8fFSKWH7YkwEM/O0DesX+5hodaaYnkiiHXNujYLuQuAH
+lV87wfcyajsEDjFkj1L/i9TdAoGBAKYfRUQv8HqmdU+doHb+iEYCHb75UMpHzQtR
+YTwpxoo3V5Kdnz9lNeYwaF7rIY59ZgMunEYHumw5U6V625nW228/hF0lZOR6cUu+
+hu2WGHWKMvdDgMJ+IcpeA8WN4cUwcN+9gHZ/vUzg4CxOTSYLvLBpGnIkOXnvUGPC
+vaTgxTSRAoGBAOHcuZ9hcUrPuVI1HVkjQQLu5mLZ3tz6linEbe/RCdJMK8JrRX4w
+ubB7gFclMYGbLlDNAJVYkydJaCy/2NAI3rfsOda+VmDqGx6z4BbSGceHhomyU1Oo
+1H7YaXsuzDkzl23HRsyp0pKJpTdghZdbVsGF8vAB8ygK3ehM233neSln
+-----END RSA PRIVATE KEY-----
diff --git a/src/boost/libs/asio/example/cpp03/ssl/client.cpp b/src/boost/libs/asio/example/cpp03/ssl/client.cpp
new file mode 100644
index 000000000..d00e15eb1
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/ssl/client.cpp
@@ -0,0 +1,157 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/bind/bind.hpp>
+#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
+
+enum { max_length = 1024 };
+
+class client
+{
+public:
+ client(boost::asio::io_context& io_context,
+ boost::asio::ssl::context& context,
+ boost::asio::ip::tcp::resolver::results_type endpoints)
+ : socket_(io_context, context)
+ {
+ socket_.set_verify_mode(boost::asio::ssl::verify_peer);
+ socket_.set_verify_callback(
+ boost::bind(&client::verify_certificate, this,
+ boost::placeholders::_1, boost::placeholders::_2));
+
+ boost::asio::async_connect(socket_.lowest_layer(), endpoints,
+ boost::bind(&client::handle_connect, this,
+ boost::asio::placeholders::error));
+ }
+
+ bool verify_certificate(bool preverified,
+ boost::asio::ssl::verify_context& ctx)
+ {
+ // The verify callback can be used to check whether the certificate that is
+ // being presented is valid for the peer. For example, RFC 2818 describes
+ // the steps involved in doing this for HTTPS. Consult the OpenSSL
+ // documentation for more details. Note that the callback is called once
+ // for each certificate in the certificate chain, starting from the root
+ // certificate authority.
+
+ // In this example we will simply print the certificate's subject name.
+ char subject_name[256];
+ X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
+ X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
+ std::cout << "Verifying " << subject_name << "\n";
+
+ return preverified;
+ }
+
+ void handle_connect(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ socket_.async_handshake(boost::asio::ssl::stream_base::client,
+ boost::bind(&client::handle_handshake, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ std::cout << "Connect failed: " << error.message() << "\n";
+ }
+ }
+
+ void handle_handshake(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Enter message: ";
+ std::cin.getline(request_, max_length);
+ size_t request_length = strlen(request_);
+
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(request_, request_length),
+ boost::bind(&client::handle_write, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ std::cout << "Handshake failed: " << error.message() << "\n";
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(reply_, bytes_transferred),
+ boost::bind(&client::handle_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ std::cout << "Write failed: " << error.message() << "\n";
+ }
+ }
+
+ void handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ std::cout << "Reply: ";
+ std::cout.write(reply_, bytes_transferred);
+ std::cout << "\n";
+ }
+ else
+ {
+ std::cout << "Read failed: " << error.message() << "\n";
+ }
+ }
+
+private:
+ boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
+ char request_[max_length];
+ char reply_[max_length];
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ boost::asio::ip::tcp::resolver resolver(io_context);
+ boost::asio::ip::tcp::resolver::results_type endpoints =
+ resolver.resolve(argv[1], argv[2]);
+
+ boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
+ ctx.load_verify_file("ca.pem");
+
+ client c(io_context, ctx, endpoints);
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/ssl/dh2048.pem b/src/boost/libs/asio/example/cpp03/ssl/dh2048.pem
new file mode 100644
index 000000000..07250cca6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/ssl/dh2048.pem
@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEAyNnxZSYc6J89mDNnqOH8bnwBiAJxcaUS3PkIEcwW8D9o2BlNq6EO
+XKMIbdfwPFZi80GMpNu3YP2A2B42sAHmb7w7ZA92QDv3JjqzR0QuS/CkMv4CEjha
+QBFwBDDWnnHBSj4w/t54ii0SH34mWcjBItI2eMtnM9J6fnvNiWqJxdt4iA4mZjZD
+qZTjIRyjgKAevzkqAlBqQRoVUUgu+9Cf29wXjVl3bE+0VU5CdFeyT+Y9yunz88mq
+rGyx1uPt+zbIfxuNLH+coY67y1ht7iZEL5WLd3wGCycRT+lYy2AL/rxGBPxStFIT
+2bOkQao6sAfb4UdGEUlwHUXZrAV51oM30wIBAg==
+-----END DH PARAMETERS-----
diff --git a/src/boost/libs/asio/example/cpp03/ssl/server.cpp b/src/boost/libs/asio/example/cpp03/ssl/server.cpp
new file mode 100644
index 000000000..fde441505
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/ssl/server.cpp
@@ -0,0 +1,170 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/bind/bind.hpp>
+#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
+
+typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
+
+class session
+{
+public:
+ session(boost::asio::io_context& io_context,
+ boost::asio::ssl::context& context)
+ : socket_(io_context, context)
+ {
+ }
+
+ ssl_socket::lowest_layer_type& socket()
+ {
+ return socket_.lowest_layer();
+ }
+
+ void start()
+ {
+ socket_.async_handshake(boost::asio::ssl::stream_base::server,
+ boost::bind(&session::handle_handshake, this,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_handshake(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ socket_.async_read_some(boost::asio::buffer(data_, max_length),
+ boost::bind(&session::handle_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ delete this;
+ }
+ }
+
+ void handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(data_, bytes_transferred),
+ boost::bind(&session::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ delete this;
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ socket_.async_read_some(boost::asio::buffer(data_, max_length),
+ boost::bind(&session::handle_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ delete this;
+ }
+ }
+
+private:
+ ssl_socket socket_;
+ enum { max_length = 1024 };
+ char data_[max_length];
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, unsigned short port)
+ : io_context_(io_context),
+ acceptor_(io_context,
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
+ context_(boost::asio::ssl::context::sslv23)
+ {
+ context_.set_options(
+ boost::asio::ssl::context::default_workarounds
+ | boost::asio::ssl::context::no_sslv2
+ | boost::asio::ssl::context::single_dh_use);
+ context_.set_password_callback(boost::bind(&server::get_password, this));
+ context_.use_certificate_chain_file("server.pem");
+ context_.use_private_key_file("server.pem", boost::asio::ssl::context::pem);
+ context_.use_tmp_dh_file("dh2048.pem");
+
+ start_accept();
+ }
+
+ std::string get_password() const
+ {
+ return "test";
+ }
+
+ void start_accept()
+ {
+ session* new_session = new session(io_context_, context_);
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(session* new_session,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_session->start();
+ }
+ else
+ {
+ delete new_session;
+ }
+
+ start_accept();
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ boost::asio::ip::tcp::acceptor acceptor_;
+ boost::asio::ssl::context context_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: server <port>\n";
+ return 1;
+ }
+
+ boost::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() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/ssl/server.pem b/src/boost/libs/asio/example/cpp03/ssl/server.pem
new file mode 100644
index 000000000..37ea6e267
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/ssl/server.pem
@@ -0,0 +1,71 @@
+-----BEGIN CERTIFICATE-----
+MIIDAzCCAesCCQD9QcRiWk0y9TANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJB
+VTEMMAoGA1UECBMDTlNXMQ8wDQYDVQQHEwZTeWRuZXkxDTALBgNVBAoTBGFzaW8w
+HhcNMTUxMTE4MjIzNzMxWhcNMjAxMTE2MjIzNzMxWjBMMQswCQYDVQQGEwJBVTEM
+MAoGA1UECBMDTlNXMQ8wDQYDVQQHEwZTeWRuZXkxDTALBgNVBAoTBGFzaW8xDzAN
+BgNVBAsTBnNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALr0
++NXSklsGJR7HYHP/H4V5+KpYrmFKva/K7iiqi+XyWEjGnj+/iImJW26phhg9GouN
+JJxdrP7/0LwpMsEC/9v09dMNAEewtYhPgD4kiUH/E/79wVmayMZZZGrpF9Rw+wWv
+q58y3L1wKge3qilX6slVDdNhqU3vBiMKEJfsjE4PKcEVjPCjVJG2562eHK9FxyjQ
+DykyH61lQKBQOiElilPQKzAO7U36yTvs+chWuUfK47B8EC+PJ5KcLEppli4ljlwE
+w01HnGxwvjDLobKm2jL6CWi3aYGWudyTsNAd7YC5C7psktBypQLBcfp7uUrrR5Bb
+PEjFHJUWIlyoYvm2OjMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAtceVW6tixFsB
+ZRhjL5aRCcbx2iMwEXd54lcP6BWe1qOcDPHoSYI1zvvGzohbEvBfqUv78S9MtzaT
+gMe5rIU9M1ZM09PyaM6ZutGpKHE8L4qcOslTt41GQFsSqPFdcbgSV20MvBzjGayR
+AI/WV0avW3oasdetJPZCR7bRbCbMbWTgclUfv5F25ENcR+BhNuilfL15owL0s4sS
+Wb4jOOHhXV9iXeS2dH0snFqv4BmQ9ZoA7zbM9lG3EU5DuxHESYkCnzJyEqqY3vWv
+PFRViCxLp5LQLmkTQ3dglVQA4x6ZaonaewdPtdhjkLUuIqDvQx5+kIaOELbSws+c
+bREYlnGrFw==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,D459676347D389E9135496D8AAFA7953
+
+wbrjxr9NHur8kgxDsgXOY9qFGKpONIQLxkuahUrDD/H+s/l7ugsLWOPsOXbjNL/7
+QYUBAx85HKm9D8BQ5g78Y82qfArap3/3IIuysDfQDh4fQodhVtmGTFiCOvudlGEp
+lq1niQRLThlxeRoFphH8KKiOTO9a/d8tdL7zRmiFwnVnhK4014mgVmgcSefA1AF5
+RbJAeMclUKddG6ltQK00ptg84CDXiMWQXFBGGmQ1av2lyFzC+xLP+qDqZAYTM9lZ
+NFRo2oEZP1ozfOVNSbXTanJgZ0DSSmhGE1PcVrHSeE/v+k1kPh3oVKi9GV51kIDC
+Zd9f/XltuDOzy1Ybn6gRy4nzNpzcwjSCIHEdSD5nxU5JfHfQ3OtnsEab7qf989iP
+s2LbCSp5uGTMvfesMIkixIZAQp2FeahZTAgU2Vx+wi5Kks68rOqeywEfzACL/Um5
+7XZu8gDs4MgRRWnxK1BbJDPifICLvSJZvgB9FKX/hk4FHFF+MtcrkalehCuLooDV
+3rfHNvRSbg7J97XQ3QC+k9ZDaumpy6n+LhaVv7BIJRBnBBtZ5Eg3DmPg6flqaHAU
+Y/8d82wb/pCmbvR3B1/Ebgs84DPJ+uZnY9M5Iwx19oqlVSR2ts/Tx619LGAm+BiQ
+7YDoC4CFmpAA8Uw0xnUbNgx94NdNmlnLeLtS50b0XlWpHKbVzmVbNYEjY6NHMlLt
+aqxWHTYTa7g/c1bg2/nxF1Lbfu5VSTROGBUuer1c3yzVuyBrjcX92Jp4BJH78qOp
+N6lY6MnH4HYRXHjzlt/S0ZzO0faPPe18Q8SWvnDVuE3fYzzL772B56d2t8eodc+/
+t6M3qJ60eXdsmgYOaPRLRUovN2xT2UUr0+biuguHyqfaVfcEU/adw+b9oUVE+5Nw
+nZHI5qhPnhLxChyZqbBl68zMUyKlfff4OyLvRGpfcHwBw6DTGjduB+DDsqqkcIB9
+2VL6nps7ZVCwMPI18siUd6cttEOf6ZXrVqHg9wfDvJOlh2NNKNLxSAFubHc90Jlj
+KejrWenXo2w6YkSUeTV4t4cWu7U8rXIkTJXDl1S6NO8DWqNDo5KjgJ2SK5NlSOJ7
+jgECn390ooneJOxxytPVQO2xppXQZZS65RHrvhB+ss5xUknly9q+ICyt6xTR9nqA
+PKkeSE6qVY0J4JgFXpkgQxgwMnjSED3LKr3jlz28pr5cC6tsc5SSlekHjT2fcSrX
+uccaVahaJRigf+q+4XzmJtdwbZU+YWGZRVMlQLA5yzPHQHDYkPpOeYU4WReND8S4
+TZRkPHaxOZ2lKQwJB93V8Vbt2MvwRy392452a33S4TcQLaWzoOljXjmZjrp2rvRz
+prBaNe8LnO4V8Oliv+H+E0UWiWFDuI+HBy4X4O9plsbw/gk64Phl9qLiBwaX/AIR
+66FXvC/czABo9oSt2jekcMtJofYr8Gr2bsJlt5ZX+GEOxz4jMv7xvz5/L3W7jVav
+pHGIv4xfN9FrXzL47O7UuUF9xZg4Rp/fxwpgEDNZmX/3DnP0ewZQUcgUX0pdqNGQ
+YVqJXcRF7KqG2NSQFuwPESZQnxU0WzSgRyUae7xg1WKfSuN8NVAzKhOgeqlD2IAo
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIJAMJYU3U6A0IRMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
+BAYTAkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChME
+YXNpbzAeFw0xNTExMTgyMjMzNDhaFw0yMDExMTYyMjMzNDhaMDsxCzAJBgNVBAYT
+AkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChMEYXNp
+bzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcRJocHdVMdLUJ/pypY
+QVSTC0t3IIgjwjazrK3kAaoIMvzPmDFxEXWcDx+nyz8kQ/E38Ir/ef2BCNGci5hu
+wkfMSuMoW9l2N4hx3QCcF46tTDEZztFxWAH7QbE2wYMlMgKZSxWimNfq0YjxEEXb
+QM0lGPLFh7Xoko29H0F3LKaaQV9u/vop3Hs0h12HeWlY4PiLp7QQTNGqbWcXycA0
+NZ/fyismireyEvPAgo6L8iXuAi7g0TVKVNlrticGGjMcMq6IMvxzEpSMkuMQ5rWj
+pZjWOoBjSYBuXdblcBRvXhOr2Ws8jJLMZfehKq9q1reQfoGV6xMnbwmumSXbWRWT
+0vkCAwEAAaOBnTCBmjAdBgNVHQ4EFgQUK/Zv/AVtfIeucJw8VEtux1dhI1YwawYD
+VR0jBGQwYoAUK/Zv/AVtfIeucJw8VEtux1dhI1ahP6Q9MDsxCzAJBgNVBAYTAkFV
+MQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChMEYXNpb4IJ
+AMJYU3U6A0IRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABLYXimq
+v/HLyIJi7Xn8AJUsICj8LKF/J24nwwiF+ibf7UkoChJURs4nN78bod/lpDVPTEVl
+gTBdV/vBJs416sCEFfsGjqB9OBYj4gb0VaJDsQd0+NMvXp0faKv2y9wgScxG9/cg
+aM7eRmyfMn1qjb6tpNxVOPpe/nFi8Vx/1orejBRaZr4zF5TkoPepfwLWQeXDUIdE
++QHZ60jZAkR5RXTVU4u3kOKcJs839pmJYyxM4H2VxpR18vy4/YdIVWkREIUM2OgT
+5iznIQIIgR56QRGP85uef+I6n0BHzrBk6du69bkQFxrFjLVGlal4bIQqSg4KGWgx
+dEdymMWzmMxpO9s=
+-----END CERTIFICATE-----
diff --git a/src/boost/libs/asio/example/cpp03/timeouts/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/timeouts/Jamfile.v2
new file mode 100644
index 000000000..dcc83c435
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/timeouts/Jamfile.v2
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe async_tcp_client : async_tcp_client.cpp ;
+exe blocking_tcp_client : blocking_tcp_client.cpp ;
+exe blocking_token_tcp_client : blocking_token_tcp_client.cpp ;
+exe blocking_udp_client : blocking_udp_client.cpp ;
+exe server : server.cpp ;
diff --git a/src/boost/libs/asio/example/cpp03/timeouts/async_tcp_client.cpp b/src/boost/libs/asio/example/cpp03/timeouts/async_tcp_client.cpp
new file mode 100644
index 000000000..1f8ba01ed
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/timeouts/async_tcp_client.cpp
@@ -0,0 +1,311 @@
+//
+// async_tcp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/bind/bind.hpp>
+#include <iostream>
+#include <string>
+
+using boost::asio::steady_timer;
+using boost::asio::ip::tcp;
+
+//
+// This class manages socket timeouts by applying the concept of a deadline.
+// Some asynchronous operations are given deadlines by which they must complete.
+// Deadlines are enforced by an "actor" that persists for the lifetime of the
+// client object:
+//
+// +----------------+
+// | |
+// | check_deadline |<---+
+// | | |
+// +----------------+ | async_wait()
+// | |
+// +---------+
+//
+// If the deadline actor determines that the deadline has expired, the socket
+// is closed and any outstanding operations are consequently cancelled.
+//
+// Connection establishment involves trying each endpoint in turn until a
+// connection is successful, or the available endpoints are exhausted. If the
+// deadline actor closes the socket, the connect actor is woken up and moves to
+// the next endpoint.
+//
+// +---------------+
+// | |
+// | start_connect |<---+
+// | | |
+// +---------------+ |
+// | |
+// async_- | +----------------+
+// connect() | | |
+// +--->| handle_connect |
+// | |
+// +----------------+
+// :
+// Once a connection is :
+// made, the connect :
+// actor forks in two - :
+// :
+// an actor for reading : and an actor for
+// inbound messages: : sending heartbeats:
+// :
+// +------------+ : +-------------+
+// | |<- - - - -+- - - - ->| |
+// | start_read | | start_write |<---+
+// | |<---+ | | |
+// +------------+ | +-------------+ | async_wait()
+// | | | |
+// async_- | +-------------+ async_- | +--------------+
+// read_- | | | write() | | |
+// until() +--->| handle_read | +--->| handle_write |
+// | | | |
+// +-------------+ +--------------+
+//
+// The input actor reads messages from the socket, where messages are delimited
+// by the newline character. The deadline for a complete message is 30 seconds.
+//
+// The heartbeat actor sends a heartbeat (a message that consists of a single
+// newline character) every 10 seconds. In this example, no deadline is applied
+// to message sending.
+//
+class client
+{
+public:
+ client(boost::asio::io_context& io_context)
+ : stopped_(false),
+ socket_(io_context),
+ deadline_(io_context),
+ heartbeat_timer_(io_context)
+ {
+ }
+
+ // Called by the user of the client class to initiate the connection process.
+ // The endpoints will have been obtained using a tcp::resolver.
+ void start(tcp::resolver::results_type endpoints)
+ {
+ // Start the connect actor.
+ endpoints_ = endpoints;
+ start_connect(endpoints_.begin());
+
+ // Start the deadline actor. You will note that we're not setting any
+ // particular deadline here. Instead, the connect and input actors will
+ // update the deadline prior to each asynchronous operation.
+ deadline_.async_wait(boost::bind(&client::check_deadline, this));
+ }
+
+ // This function terminates all the actors to shut down the connection. It
+ // may be called by the user of the client class, or by the class itself in
+ // response to graceful termination or an unrecoverable error.
+ void stop()
+ {
+ stopped_ = true;
+ boost::system::error_code ignored_ec;
+ socket_.close(ignored_ec);
+ deadline_.cancel();
+ heartbeat_timer_.cancel();
+ }
+
+private:
+ void start_connect(tcp::resolver::results_type::iterator endpoint_iter)
+ {
+ if (endpoint_iter != endpoints_.end())
+ {
+ std::cout << "Trying " << endpoint_iter->endpoint() << "...\n";
+
+ // Set a deadline for the connect operation.
+ deadline_.expires_after(boost::asio::chrono::seconds(60));
+
+ // Start the asynchronous connect operation.
+ socket_.async_connect(endpoint_iter->endpoint(),
+ boost::bind(&client::handle_connect, this,
+ boost::placeholders::_1, endpoint_iter));
+ }
+ else
+ {
+ // There are no more endpoints to try. Shut down the client.
+ stop();
+ }
+ }
+
+ void handle_connect(const boost::system::error_code& ec,
+ tcp::resolver::results_type::iterator endpoint_iter)
+ {
+ if (stopped_)
+ return;
+
+ // The async_connect() function automatically opens the socket at the start
+ // of the asynchronous operation. If the socket is closed at this time then
+ // the timeout handler must have run first.
+ if (!socket_.is_open())
+ {
+ std::cout << "Connect timed out\n";
+
+ // Try the next available endpoint.
+ start_connect(++endpoint_iter);
+ }
+
+ // Check if the connect operation failed before the deadline expired.
+ else if (ec)
+ {
+ std::cout << "Connect error: " << ec.message() << "\n";
+
+ // We need to close the socket used in the previous connection attempt
+ // before starting a new one.
+ socket_.close();
+
+ // Try the next available endpoint.
+ start_connect(++endpoint_iter);
+ }
+
+ // Otherwise we have successfully established a connection.
+ else
+ {
+ std::cout << "Connected to " << endpoint_iter->endpoint() << "\n";
+
+ // Start the input actor.
+ start_read();
+
+ // Start the heartbeat actor.
+ start_write();
+ }
+ }
+
+ void start_read()
+ {
+ // Set a deadline for the read operation.
+ deadline_.expires_after(boost::asio::chrono::seconds(30));
+
+ // Start an asynchronous operation to read a newline-delimited message.
+ boost::asio::async_read_until(socket_,
+ boost::asio::dynamic_buffer(input_buffer_), '\n',
+ boost::bind(&client::handle_read, this,
+ boost::placeholders::_1, boost::placeholders::_2));
+ }
+
+ void handle_read(const boost::system::error_code& ec, std::size_t n)
+ {
+ if (stopped_)
+ return;
+
+ if (!ec)
+ {
+ // Extract the newline-delimited message from the buffer.
+ std::string line(input_buffer_.substr(0, n - 1));
+ input_buffer_.erase(0, n);
+
+ // Empty messages are heartbeats and so ignored.
+ if (!line.empty())
+ {
+ std::cout << "Received: " << line << "\n";
+ }
+
+ start_read();
+ }
+ else
+ {
+ std::cout << "Error on receive: " << ec.message() << "\n";
+
+ stop();
+ }
+ }
+
+ void start_write()
+ {
+ if (stopped_)
+ return;
+
+ // Start an asynchronous operation to send a heartbeat message.
+ boost::asio::async_write(socket_, boost::asio::buffer("\n", 1),
+ boost::bind(&client::handle_write, this, boost::placeholders::_1));
+ }
+
+ void handle_write(const boost::system::error_code& ec)
+ {
+ if (stopped_)
+ return;
+
+ if (!ec)
+ {
+ // Wait 10 seconds before sending the next heartbeat.
+ heartbeat_timer_.expires_after(boost::asio::chrono::seconds(10));
+ heartbeat_timer_.async_wait(boost::bind(&client::start_write, this));
+ }
+ else
+ {
+ std::cout << "Error on heartbeat: " << ec.message() << "\n";
+
+ stop();
+ }
+ }
+
+ void check_deadline()
+ {
+ if (stopped_)
+ return;
+
+ // Check whether the deadline has passed. We compare the deadline against
+ // the current time since a new asynchronous operation may have moved the
+ // deadline before this actor had a chance to run.
+ if (deadline_.expiry() <= steady_timer::clock_type::now())
+ {
+ // The deadline has passed. The socket is closed so that any outstanding
+ // asynchronous operations are cancelled.
+ socket_.close();
+
+ // There is no longer an active deadline. The expiry is set to the
+ // maximum time point so that the actor takes no action until a new
+ // deadline is set.
+ deadline_.expires_at(steady_timer::time_point::max());
+ }
+
+ // Put the actor back to sleep.
+ deadline_.async_wait(boost::bind(&client::check_deadline, this));
+ }
+
+private:
+ bool stopped_;
+ tcp::resolver::results_type endpoints_;
+ tcp::socket socket_;
+ std::string input_buffer_;
+ steady_timer deadline_;
+ steady_timer heartbeat_timer_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+ tcp::resolver r(io_context);
+ client c(io_context);
+
+ c.start(r.resolve(argv[1], argv[2]));
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/timeouts/blocking_tcp_client.cpp b/src/boost/libs/asio/example/cpp03/timeouts/blocking_tcp_client.cpp
new file mode 100644
index 000000000..a0bbaeac6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/timeouts/blocking_tcp_client.cpp
@@ -0,0 +1,191 @@
+//
+// blocking_tcp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/buffer.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+
+using boost::asio::ip::tcp;
+using boost::lambda::bind;
+using boost::lambda::var;
+using boost::lambda::_1;
+using boost::lambda::_2;
+
+//----------------------------------------------------------------------
+
+//
+// This class manages socket timeouts by running the io_context using the timed
+// io_context::run_for() member function. Each asynchronous operation is given
+// a timeout within which it must complete. The socket operations themselves
+// use boost::lambda function objects as completion handlers. For a given
+// socket operation, the client object runs the io_context to block thread
+// execution until the operation completes or the timeout is reached. If the
+// io_context::run_for() function times out, the socket is closed and the
+// outstanding asynchronous operation is cancelled.
+//
+class client
+{
+public:
+ client()
+ : socket_(io_context_)
+ {
+ }
+
+ void connect(const std::string& host, const std::string& service,
+ boost::asio::chrono::steady_clock::duration timeout)
+ {
+ // Resolve the host name and service to a list of endpoints.
+ tcp::resolver::results_type endpoints =
+ tcp::resolver(io_context_).resolve(host, service);
+
+ // Start the asynchronous operation itself. The boost::lambda function
+ // object is used as a callback and will update the ec variable when the
+ // operation completes. The blocking_udp_client.cpp example shows how you
+ // can use boost::bind rather than boost::lambda.
+ boost::system::error_code ec;
+ boost::asio::async_connect(socket_, endpoints, var(ec) = _1);
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether a connection was successfully established.
+ if (ec)
+ throw boost::system::system_error(ec);
+ }
+
+ std::string read_line(boost::asio::chrono::steady_clock::duration timeout)
+ {
+ // Start the asynchronous operation. The boost::lambda function object is
+ // used as a callback and will update the ec variable when the operation
+ // completes. The blocking_udp_client.cpp example shows how you can use
+ // boost::bind rather than boost::lambda.
+ boost::system::error_code ec;
+ std::size_t n = 0;
+ boost::asio::async_read_until(socket_,
+ boost::asio::dynamic_buffer(input_buffer_),
+ '\n', (var(ec) = _1, var(n) = _2));
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether the read completed successfully.
+ if (ec)
+ throw boost::system::system_error(ec);
+
+ std::string line(input_buffer_.substr(0, n - 1));
+ input_buffer_.erase(0, n);
+ return line;
+ }
+
+ void write_line(const std::string& line,
+ boost::asio::chrono::steady_clock::duration timeout)
+ {
+ std::string data = line + "\n";
+
+ // Start the asynchronous operation. The boost::lambda function object is
+ // used as a callback and will update the ec variable when the operation
+ // completes. The blocking_udp_client.cpp example shows how you can use
+ // boost::bind rather than boost::lambda.
+ boost::system::error_code ec;
+ boost::asio::async_write(socket_, boost::asio::buffer(data), var(ec) = _1);
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether the read completed successfully.
+ if (ec)
+ throw boost::system::system_error(ec);
+ }
+
+private:
+ void run(boost::asio::chrono::steady_clock::duration timeout)
+ {
+ // Restart the io_context, as it may have been left in the "stopped" state
+ // by a previous operation.
+ io_context_.restart();
+
+ // Block until the asynchronous operation has completed, or timed out. If
+ // 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);
+
+ // If the asynchronous operation completed successfully then the io_context
+ // would have been stopped due to running out of work. If it was not
+ // stopped, then the io_context::run_for call must have timed out.
+ if (!io_context_.stopped())
+ {
+ // Close the socket to cancel the outstanding asynchronous operation.
+ socket_.close();
+
+ // Run the io_context again until the operation completes.
+ io_context_.run();
+ }
+ }
+
+ boost::asio::io_context io_context_;
+ tcp::socket socket_;
+ std::string input_buffer_;
+};
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 4)
+ {
+ std::cerr << "Usage: blocking_tcp_client <host> <port> <message>\n";
+ return 1;
+ }
+
+ client c;
+ c.connect(argv[1], argv[2], boost::asio::chrono::seconds(10));
+
+ boost::asio::chrono::steady_clock::time_point time_sent =
+ boost::asio::chrono::steady_clock::now();
+
+ c.write_line(argv[3], boost::asio::chrono::seconds(10));
+
+ for (;;)
+ {
+ std::string line = c.read_line(boost::asio::chrono::seconds(10));
+
+ // Keep going until we get back the line that was sent.
+ if (line == argv[3])
+ break;
+ }
+
+ boost::asio::chrono::steady_clock::time_point time_received =
+ boost::asio::chrono::steady_clock::now();
+
+ std::cout << "Round trip time: ";
+ std::cout << boost::asio::chrono::duration_cast<
+ boost::asio::chrono::microseconds>(
+ time_received - time_sent).count();
+ std::cout << " microseconds\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/timeouts/blocking_token_tcp_client.cpp b/src/boost/libs/asio/example/cpp03/timeouts/blocking_token_tcp_client.cpp
new file mode 100644
index 000000000..effb491c2
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/timeouts/blocking_token_tcp_client.cpp
@@ -0,0 +1,202 @@
+//
+// blocking_token_tcp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/connect.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/streambuf.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <string>
+
+using boost::asio::ip::tcp;
+
+// We will use our sockets only with an io_context.
+typedef boost::asio::basic_stream_socket<tcp,
+ boost::asio::io_context::executor_type> tcp_socket;
+
+//----------------------------------------------------------------------
+
+// A custom completion token that makes asynchronous operations behave as
+// though they are blocking calls with a timeout.
+struct close_after
+{
+ close_after(boost::asio::chrono::steady_clock::duration t, tcp_socket& s)
+ : timeout_(t), socket_(s)
+ {
+ }
+
+ // The maximum time to wait for an asynchronous operation to complete.
+ boost::asio::chrono::steady_clock::duration timeout_;
+
+ // The socket to be closed if the operation does not complete in time.
+ tcp_socket& socket_;
+};
+
+namespace boost {
+namespace asio {
+
+// The async_result template is specialised to allow the close_after token to
+// be used with asynchronous operations that have a completion signature of
+// void(error_code, T). Generalising this for all completion signature forms is
+// left as an exercise for the reader.
+template <typename T>
+class async_result<close_after, void(boost::system::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()(boost::system::error_code ec, T t)
+ {
+ *ec_ = ec;
+ *t_ = t;
+ }
+
+ private:
+ friend class async_result;
+ close_after token_;
+ boost::system::error_code* ec_;
+ 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.ec_ = &ec_;
+ 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()
+ {
+ boost::asio::io_context& io_context = socket_.get_executor().context();
+
+ // Restart the io_context, as it may have been left in the "stopped" state
+ // by a previous operation.
+ io_context.restart();
+
+ // Block until the asynchronous operation has completed, or timed out. If
+ // 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_);
+
+ // If the asynchronous operation completed successfully then the io_context
+ // would have been stopped due to running out of work. If it was not
+ // stopped, then the io_context::run_for call must have timed out and the
+ // operation is still incomplete.
+ if (!io_context.stopped())
+ {
+ // Close the socket to cancel the outstanding asynchronous operation.
+ 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 ec_ ? throw boost::system::system_error(ec_) : t_;
+ }
+
+private:
+ boost::asio::chrono::steady_clock::duration timeout_;
+ tcp_socket& socket_;
+ boost::system::error_code ec_;
+ T t_;
+};
+
+} // namespace asio
+} // namespace boost
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 4)
+ {
+ std::cerr << "Usage: blocking_tcp_client <host> <port> <message>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ // Resolve the host name and service to a list of endpoints.
+ tcp::resolver::results_type endpoints =
+ tcp::resolver(io_context).resolve(argv[1], argv[2]);
+
+ tcp_socket socket(io_context);
+
+ // Run an asynchronous connect operation with a timeout.
+ boost::asio::async_connect(socket, endpoints,
+ close_after(boost::asio::chrono::seconds(10), socket));
+
+ boost::asio::chrono::steady_clock::time_point time_sent =
+ boost::asio::chrono::steady_clock::now();
+
+ // Run an asynchronous write operation with a timeout.
+ std::string msg = argv[3] + std::string("\n");
+ boost::asio::async_write(socket, boost::asio::buffer(msg),
+ close_after(boost::asio::chrono::seconds(10), socket));
+
+ for (std::string input_buffer;;)
+ {
+ // Run an asynchronous read operation with a timeout.
+ std::size_t n = boost::asio::async_read_until(socket,
+ boost::asio::dynamic_buffer(input_buffer), '\n',
+ close_after(boost::asio::chrono::seconds(10), socket));
+
+ std::string line(input_buffer.substr(0, n - 1));
+ input_buffer.erase(0, n);
+
+ // Keep going until we get back the line that was sent.
+ if (line == argv[3])
+ break;
+ }
+
+ boost::asio::chrono::steady_clock::time_point time_received =
+ boost::asio::chrono::steady_clock::now();
+
+ std::cout << "Round trip time: ";
+ std::cout << boost::asio::chrono::duration_cast<
+ boost::asio::chrono::microseconds>(
+ time_received - time_sent).count();
+ std::cout << " microseconds\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/timeouts/blocking_udp_client.cpp b/src/boost/libs/asio/example/cpp03/timeouts/blocking_udp_client.cpp
new file mode 100644
index 000000000..95c3480c1
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/timeouts/blocking_udp_client.cpp
@@ -0,0 +1,154 @@
+//
+// blocking_udp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <cstdlib>
+#include <boost/bind/bind.hpp>
+#include <iostream>
+
+using boost::asio::ip::udp;
+
+//----------------------------------------------------------------------
+
+//
+// This class manages socket timeouts by running the io_context using the timed
+// io_context::run_for() member function. Each asynchronous operation is given
+// a timeout within which it must complete. The socket operations themselves
+// use boost::bind to specify the completion handler:
+//
+// +---------------+
+// | |
+// | receive |
+// | |
+// +---------------+
+// |
+// async_- | +----------------+
+// receive() | | |
+// +--->| handle_receive |
+// | |
+// +----------------+
+//
+// For a given socket operation, the client object runs the io_context to block
+// thread execution until the operation completes or the timeout is reached. If
+// the io_context::run_for() function times out, the socket is closed and the
+// outstanding asynchronous operation is cancelled.
+//
+class client
+{
+public:
+ client(const udp::endpoint& listen_endpoint)
+ : socket_(io_context_, listen_endpoint)
+ {
+ }
+
+ std::size_t receive(const boost::asio::mutable_buffer& buffer,
+ boost::asio::chrono::steady_clock::duration timeout,
+ boost::system::error_code& ec)
+ {
+ // Start the asynchronous operation. The handle_receive function used as a
+ // callback will update the ec and length variables.
+ std::size_t length = 0;
+ socket_.async_receive(boost::asio::buffer(buffer),
+ boost::bind(&client::handle_receive,
+ boost::placeholders::_1, boost::placeholders::_2, &ec, &length));
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ return length;
+ }
+
+private:
+ void run(boost::asio::chrono::steady_clock::duration timeout)
+ {
+ // Restart the io_context, as it may have been left in the "stopped" state
+ // by a previous operation.
+ io_context_.restart();
+
+ // Block until the asynchronous operation has completed, or timed out. If
+ // 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);
+
+ // If the asynchronous operation completed successfully then the io_context
+ // would have been stopped due to running out of work. If it was not
+ // stopped, then the io_context::run_for call must have timed out.
+ if (!io_context_.stopped())
+ {
+ // Cancel the outstanding asynchronous operation.
+ socket_.cancel();
+
+ // Run the io_context again until the operation completes.
+ io_context_.run();
+ }
+ }
+
+ static void handle_receive(
+ const boost::system::error_code& ec, std::size_t length,
+ boost::system::error_code* out_ec, std::size_t* out_length)
+ {
+ *out_ec = ec;
+ *out_length = length;
+ }
+
+private:
+ boost::asio::io_context io_context_;
+ udp::socket socket_;
+};
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ using namespace std; // For atoi.
+
+ if (argc != 3)
+ {
+ std::cerr << "Usage: blocking_udp_client <listen_addr> <listen_port>\n";
+ return 1;
+ }
+
+ udp::endpoint listen_endpoint(
+ boost::asio::ip::make_address(argv[1]),
+ std::atoi(argv[2]));
+
+ client c(listen_endpoint);
+
+ for (;;)
+ {
+ char data[1024];
+ boost::system::error_code ec;
+ std::size_t n = c.receive(boost::asio::buffer(data),
+ boost::asio::chrono::seconds(10), ec);
+
+ if (ec)
+ {
+ std::cout << "Receive error: " << ec.message() << "\n";
+ }
+ else
+ {
+ std::cout << "Received: ";
+ std::cout.write(data, n);
+ std::cout << "\n";
+ }
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/timeouts/server.cpp b/src/boost/libs/asio/example/cpp03/timeouts/server.cpp
new file mode 100644
index 000000000..0b48ea01d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/timeouts/server.cpp
@@ -0,0 +1,433 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <algorithm>
+#include <cstdlib>
+#include <deque>
+#include <iostream>
+#include <set>
+#include <string>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/write.hpp>
+
+using boost::asio::steady_timer;
+using boost::asio::ip::tcp;
+using boost::asio::ip::udp;
+
+//----------------------------------------------------------------------
+
+class subscriber
+{
+public:
+ virtual ~subscriber() {}
+ virtual void deliver(const std::string& msg) = 0;
+};
+
+typedef boost::shared_ptr<subscriber> subscriber_ptr;
+
+//----------------------------------------------------------------------
+
+class channel
+{
+public:
+ void join(subscriber_ptr subscriber)
+ {
+ subscribers_.insert(subscriber);
+ }
+
+ void leave(subscriber_ptr subscriber)
+ {
+ subscribers_.erase(subscriber);
+ }
+
+ void deliver(const std::string& msg)
+ {
+ std::for_each(subscribers_.begin(), subscribers_.end(),
+ boost::bind(&subscriber::deliver,
+ boost::placeholders::_1, boost::ref(msg)));
+ }
+
+private:
+ std::set<subscriber_ptr> subscribers_;
+};
+
+//----------------------------------------------------------------------
+
+//
+// This class manages socket timeouts by applying the concept of a deadline.
+// Some asynchronous operations are given deadlines by which they must complete.
+// Deadlines are enforced by two "actors" that persist for the lifetime of the
+// session object, one for input and one for output:
+//
+// +----------------+ +----------------+
+// | | | |
+// | check_deadline |<---+ | check_deadline |<---+
+// | | | async_wait() | | | async_wait()
+// +----------------+ | on input +----------------+ | on output
+// | | deadline | | deadline
+// +---------+ +---------+
+//
+// If either deadline actor determines that the corresponding deadline has
+// expired, the socket is closed and any outstanding operations are cancelled.
+//
+// The input actor reads messages from the socket, where messages are delimited
+// by the newline character:
+//
+// +------------+
+// | |
+// | start_read |<---+
+// | | |
+// +------------+ |
+// | |
+// async_- | +-------------+
+// read_- | | |
+// until() +--->| handle_read |
+// | |
+// +-------------+
+//
+// The deadline for receiving a complete message is 30 seconds. If a non-empty
+// message is received, it is delivered to all subscribers. If a heartbeat (a
+// message that consists of a single newline character) is received, a heartbeat
+// is enqueued for the client, provided there are no other messages waiting to
+// be sent.
+//
+// The output actor is responsible for sending messages to the client:
+//
+// +--------------+
+// | |<---------------------+
+// | await_output | |
+// | |<---+ |
+// +--------------+ | |
+// | | | async_wait() |
+// | +--------+ |
+// V |
+// +-------------+ +--------------+
+// | | async_write() | |
+// | start_write |-------------->| handle_write |
+// | | | |
+// +-------------+ +--------------+
+//
+// The output actor first waits for an output message to be enqueued. It does
+// this by using a steady_timer as an asynchronous condition variable. The
+// steady_timer will be signalled whenever the output queue is non-empty.
+//
+// Once a message is available, it is sent to the client. The deadline for
+// sending a complete message is 30 seconds. After the message is successfully
+// sent, the output actor again waits for the output queue to become non-empty.
+//
+class tcp_session
+ : public subscriber,
+ public boost::enable_shared_from_this<tcp_session>
+{
+public:
+ tcp_session(boost::asio::io_context& io_context, channel& ch)
+ : channel_(ch),
+ socket_(io_context),
+ input_deadline_(io_context),
+ non_empty_output_queue_(io_context),
+ output_deadline_(io_context)
+ {
+ input_deadline_.expires_at(steady_timer::time_point::max());
+ output_deadline_.expires_at(steady_timer::time_point::max());
+
+ // The non_empty_output_queue_ steady_timer is set to the maximum time
+ // point whenever the output queue is empty. This ensures that the output
+ // actor stays asleep until a message is put into the queue.
+ non_empty_output_queue_.expires_at(steady_timer::time_point::max());
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ // Called by the server object to initiate the four actors.
+ void start()
+ {
+ channel_.join(shared_from_this());
+
+ start_read();
+
+ input_deadline_.async_wait(
+ boost::bind(&tcp_session::check_deadline,
+ shared_from_this(), &input_deadline_));
+
+ await_output();
+
+ output_deadline_.async_wait(
+ boost::bind(&tcp_session::check_deadline,
+ shared_from_this(), &output_deadline_));
+ }
+
+private:
+ void stop()
+ {
+ channel_.leave(shared_from_this());
+
+ boost::system::error_code ignored_ec;
+ socket_.close(ignored_ec);
+ input_deadline_.cancel();
+ non_empty_output_queue_.cancel();
+ output_deadline_.cancel();
+ }
+
+ bool stopped() const
+ {
+ return !socket_.is_open();
+ }
+
+ void deliver(const std::string& msg)
+ {
+ output_queue_.push_back(msg + "\n");
+
+ // Signal that the output queue contains messages. Modifying the expiry
+ // will wake the output actor, if it is waiting on the timer.
+ non_empty_output_queue_.expires_at(steady_timer::time_point::min());
+ }
+
+ void start_read()
+ {
+ // Set a deadline for the read operation.
+ input_deadline_.expires_after(boost::asio::chrono::seconds(30));
+
+ // Start an asynchronous operation to read a newline-delimited message.
+ boost::asio::async_read_until(socket_,
+ boost::asio::dynamic_buffer(input_buffer_), '\n',
+ boost::bind(&tcp_session::handle_read, shared_from_this(),
+ boost::placeholders::_1, boost::placeholders::_2));
+ }
+
+ void handle_read(const boost::system::error_code& ec, std::size_t n)
+ {
+ if (stopped())
+ return;
+
+ if (!ec)
+ {
+ // Extract the newline-delimited message from the buffer.
+ std::string msg(input_buffer_.substr(0, n - 1));
+ input_buffer_.erase(0, n);
+
+ if (!msg.empty())
+ {
+ channel_.deliver(msg);
+ }
+ else
+ {
+ // We received a heartbeat message from the client. If there's nothing
+ // else being sent or ready to be sent, send a heartbeat right back.
+ if (output_queue_.empty())
+ {
+ output_queue_.push_back("\n");
+
+ // Signal that the output queue contains messages. Modifying the
+ // expiry will wake the output actor, if it is waiting on the timer.
+ non_empty_output_queue_.expires_at(steady_timer::time_point::min());
+ }
+ }
+
+ start_read();
+ }
+ else
+ {
+ stop();
+ }
+ }
+
+ void await_output()
+ {
+ if (stopped())
+ return;
+
+ if (output_queue_.empty())
+ {
+ // There are no messages that are ready to be sent. The actor goes to
+ // sleep by waiting on the non_empty_output_queue_ timer. When a new
+ // message is added, the timer will be modified and the actor will wake.
+ non_empty_output_queue_.expires_at(steady_timer::time_point::max());
+ non_empty_output_queue_.async_wait(
+ boost::bind(&tcp_session::await_output, shared_from_this()));
+ }
+ else
+ {
+ start_write();
+ }
+ }
+
+ void start_write()
+ {
+ // Set a deadline for the write operation.
+ output_deadline_.expires_after(boost::asio::chrono::seconds(30));
+
+ // Start an asynchronous operation to send a message.
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(output_queue_.front()),
+ boost::bind(&tcp_session::handle_write,
+ shared_from_this(), boost::placeholders::_1));
+ }
+
+ void handle_write(const boost::system::error_code& ec)
+ {
+ if (stopped())
+ return;
+
+ if (!ec)
+ {
+ output_queue_.pop_front();
+
+ await_output();
+ }
+ else
+ {
+ stop();
+ }
+ }
+
+ void check_deadline(steady_timer* deadline)
+ {
+ if (stopped())
+ return;
+
+ // Check whether the deadline has passed. We compare the deadline against
+ // the current time since a new asynchronous operation may have moved the
+ // deadline before this actor had a chance to run.
+ if (deadline->expiry() <= steady_timer::clock_type::now())
+ {
+ // The deadline has passed. Stop the session. The other actors will
+ // terminate as soon as possible.
+ stop();
+ }
+ else
+ {
+ // Put the actor back to sleep.
+ deadline->async_wait(
+ boost::bind(&tcp_session::check_deadline,
+ shared_from_this(), deadline));
+ }
+ }
+
+ channel& channel_;
+ tcp::socket socket_;
+ std::string input_buffer_;
+ steady_timer input_deadline_;
+ std::deque<std::string> output_queue_;
+ steady_timer non_empty_output_queue_;
+ steady_timer output_deadline_;
+};
+
+typedef boost::shared_ptr<tcp_session> tcp_session_ptr;
+
+//----------------------------------------------------------------------
+
+class udp_broadcaster
+ : public subscriber
+{
+public:
+ udp_broadcaster(boost::asio::io_context& io_context,
+ const udp::endpoint& broadcast_endpoint)
+ : socket_(io_context)
+ {
+ socket_.connect(broadcast_endpoint);
+ socket_.set_option(udp::socket::broadcast(true));
+ }
+
+private:
+ void deliver(const std::string& msg)
+ {
+ boost::system::error_code ignored_ec;
+ socket_.send(boost::asio::buffer(msg), 0, ignored_ec);
+ }
+
+ udp::socket socket_;
+};
+
+//----------------------------------------------------------------------
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context,
+ const tcp::endpoint& listen_endpoint,
+ const udp::endpoint& broadcast_endpoint)
+ : io_context_(io_context),
+ acceptor_(io_context, listen_endpoint)
+ {
+ subscriber_ptr bc(new udp_broadcaster(io_context_, broadcast_endpoint));
+ channel_.join(bc);
+
+ start_accept();
+ }
+
+ void start_accept()
+ {
+ tcp_session_ptr new_session(new tcp_session(io_context_, channel_));
+
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept,
+ this, new_session, boost::placeholders::_1));
+ }
+
+ void handle_accept(tcp_session_ptr session,
+ const boost::system::error_code& ec)
+ {
+ if (!ec)
+ {
+ session->start();
+ }
+
+ start_accept();
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ tcp::acceptor acceptor_;
+ channel channel_;
+};
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ using namespace std; // For atoi.
+
+ if (argc != 4)
+ {
+ std::cerr << "Usage: server <listen_port> <bcast_address> <bcast_port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ tcp::endpoint listen_endpoint(tcp::v4(), atoi(argv[1]));
+
+ udp::endpoint broadcast_endpoint(
+ boost::asio::ip::make_address(argv[2]), atoi(argv[3]));
+
+ server s(io_context, listen_endpoint, broadcast_endpoint);
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/timers/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/timers/Jamfile.v2
new file mode 100644
index 000000000..7c57391ed
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/timers/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe time_t_timer
+ : time_t_timer.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/timers/time_t_timer.cpp b/src/boost/libs/asio/example/cpp03/timers/time_t_timer.cpp
new file mode 100644
index 000000000..6efc29ebc
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/timers/time_t_timer.cpp
@@ -0,0 +1,106 @@
+//
+// time_t_timer.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <ctime>
+#include <iostream>
+
+// A custom implementation of the Clock concept from the standard C++ library.
+struct time_t_clock
+{
+ // The duration type.
+ typedef boost::asio::chrono::steady_clock::duration duration;
+
+ // The duration's underlying arithmetic representation.
+ typedef duration::rep rep;
+
+ // The ratio representing the duration's tick period.
+ typedef duration::period period;
+
+ // An absolute time point represented using the clock.
+ typedef boost::asio::chrono::time_point<time_t_clock> time_point;
+
+ // The clock is not monotonically increasing.
+ static const bool is_steady = false;
+
+ // Get the current time.
+ static time_point now()
+ {
+ return time_point() + boost::asio::chrono::seconds(std::time(0));
+ }
+};
+
+// The boost::asio::basic_waitable_timer template accepts an optional WaitTraits
+// template parameter. The underlying time_t clock has one-second granularity,
+// so these traits may be customised to reduce the latency between the clock
+// ticking over and a wait operation's completion. When the timeout is near
+// (less than one second away) we poll the clock more frequently to detect the
+// time change closer to when it occurs. The user can select the appropriate
+// trade off between accuracy and the increased CPU cost of polling. In extreme
+// cases, a zero duration may be returned to make the timers as accurate as
+// possible, albeit with 100% CPU usage.
+struct time_t_wait_traits
+{
+ // Determine how long until the clock should be next polled to determine
+ // whether the duration has elapsed.
+ static time_t_clock::duration to_wait_duration(
+ const time_t_clock::duration& d)
+ {
+ if (d > boost::asio::chrono::seconds(1))
+ return d - boost::asio::chrono::seconds(1);
+ else if (d > boost::asio::chrono::seconds(0))
+ return boost::asio::chrono::milliseconds(10);
+ else
+ return boost::asio::chrono::seconds(0);
+ }
+
+ // Determine how long until the clock should be next polled to determine
+ // whether the absoluate time has been reached.
+ static time_t_clock::duration to_wait_duration(
+ const time_t_clock::time_point& t)
+ {
+ return to_wait_duration(t - time_t_clock::now());
+ }
+};
+
+typedef boost::asio::basic_waitable_timer<
+ time_t_clock, time_t_wait_traits> time_t_timer;
+
+void handle_timeout(const boost::system::error_code&)
+{
+ std::cout << "handle_timeout\n";
+}
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context;
+
+ time_t_timer timer(io_context);
+
+ timer.expires_after(boost::asio::chrono::seconds(5));
+ std::cout << "Starting synchronous wait\n";
+ timer.wait();
+ std::cout << "Finished synchronous wait\n";
+
+ timer.expires_after(boost::asio::chrono::seconds(5));
+ std::cout << "Starting asynchronous wait\n";
+ timer.async_wait(&handle_timeout);
+ io_context.run();
+ std::cout << "Finished asynchronous wait\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/tutorial/Jamfile.v2
new file mode 100644
index 000000000..3cc39ec0e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/Jamfile.v2
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+obj timer1.obj : timer1/timer.cpp ;
+exe timer1 : timer1.obj ;
+
+obj timer2.obj : timer2/timer.cpp ;
+exe timer2 : timer2.obj ;
+
+obj timer3.obj : timer3/timer.cpp ;
+exe timer3 : timer3.obj ;
+
+obj timer4.obj : timer4/timer.cpp ;
+exe timer4 : timer4.obj ;
+
+obj timer5.obj : timer5/timer.cpp ;
+exe timer5 : timer5.obj ;
+
+obj daytime1_client.obj : daytime1/client.cpp ;
+exe daytime1_client : daytime1_client.obj ;
+
+obj daytime2_server.obj : daytime2/server.cpp ;
+exe daytime2_server : daytime2_server.obj ;
+
+obj daytime3_server.obj : daytime3/server.cpp ;
+exe daytime3_server : daytime3_server.obj ;
+
+obj daytime4_client.obj : daytime4/client.cpp ;
+exe daytime4_client : daytime4_client.obj ;
+
+obj daytime5_server.obj : daytime5/server.cpp ;
+exe daytime5_server : daytime5_server.obj ;
+
+obj daytime6_server.obj : daytime6/server.cpp ;
+exe daytime6_server : daytime6_server.obj ;
+
+obj daytime7_server.obj : daytime7/server.cpp ;
+exe daytime7_server : daytime7_server.obj ;
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/daytime1/client.cpp b/src/boost/libs/asio/example/cpp03/tutorial/daytime1/client.cpp
new file mode 100644
index 000000000..42acecaef
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/daytime1/client.cpp
@@ -0,0 +1,57 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/array.hpp>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: client <host>" << std::endl;
+ return 1;
+ }
+
+ boost::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);
+ boost::asio::connect(socket, endpoints);
+
+ for (;;)
+ {
+ boost::array<char, 128> buf;
+ boost::system::error_code error;
+
+ size_t len = socket.read_some(boost::asio::buffer(buf), error);
+
+ if (error == boost::asio::error::eof)
+ break; // Connection closed cleanly by peer.
+ else if (error)
+ throw boost::system::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/src/boost/libs/asio/example/cpp03/tutorial/daytime2/server.cpp b/src/boost/libs/asio/example/cpp03/tutorial/daytime2/server.cpp
new file mode 100644
index 000000000..332eb159f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/daytime2/server.cpp
@@ -0,0 +1,50 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+
+using boost::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
+ {
+ boost::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();
+
+ boost::system::error_code ignored_error;
+ boost::asio::write(socket, boost::asio::buffer(message), ignored_error);
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/daytime3/server.cpp b/src/boost/libs/asio/example/cpp03/tutorial/daytime3/server.cpp
new file mode 100644
index 000000000..01a2a8838
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/daytime3/server.cpp
@@ -0,0 +1,119 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/asio.hpp>
+
+using boost::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 boost::enable_shared_from_this<tcp_connection>
+{
+public:
+ typedef boost::shared_ptr<tcp_connection> pointer;
+
+ static pointer create(boost::asio::io_context& io_context)
+ {
+ return pointer(new tcp_connection(io_context));
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ message_ = make_daytime_string();
+
+ boost::asio::async_write(socket_, boost::asio::buffer(message_),
+ boost::bind(&tcp_connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+private:
+ tcp_connection(boost::asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ void handle_write(const boost::system::error_code& /*error*/,
+ size_t /*bytes_transferred*/)
+ {
+ }
+
+ tcp::socket socket_;
+ std::string message_;
+};
+
+class tcp_server
+{
+public:
+ tcp_server(boost::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(),
+ boost::bind(&tcp_server::handle_accept, this, new_connection,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(tcp_connection::pointer new_connection,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_connection->start();
+ }
+
+ start_accept();
+ }
+
+ boost::asio::io_context& io_context_;
+ tcp::acceptor acceptor_;
+};
+
+int main()
+{
+ try
+ {
+ boost::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/src/boost/libs/asio/example/cpp03/tutorial/daytime4/client.cpp b/src/boost/libs/asio/example/cpp03/tutorial/daytime4/client.cpp
new file mode 100644
index 000000000..df3092da6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/daytime4/client.cpp
@@ -0,0 +1,52 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/array.hpp>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::udp;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: client <host>" << std::endl;
+ return 1;
+ }
+
+ boost::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());
+
+ boost::array<char, 1> send_buf = {{ 0 }};
+ socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);
+
+ boost::array<char, 128> recv_buf;
+ udp::endpoint sender_endpoint;
+ size_t len = socket.receive_from(
+ boost::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/src/boost/libs/asio/example/cpp03/tutorial/daytime5/server.cpp b/src/boost/libs/asio/example/cpp03/tutorial/daytime5/server.cpp
new file mode 100644
index 000000000..316a72923
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/daytime5/server.cpp
@@ -0,0 +1,53 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/array.hpp>
+#include <boost/asio.hpp>
+
+using boost::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
+ {
+ boost::asio::io_context io_context;
+
+ udp::socket socket(io_context, udp::endpoint(udp::v4(), 13));
+
+ for (;;)
+ {
+ boost::array<char, 1> recv_buf;
+ udp::endpoint remote_endpoint;
+ socket.receive_from(boost::asio::buffer(recv_buf), remote_endpoint);
+
+ std::string message = make_daytime_string();
+
+ boost::system::error_code ignored_error;
+ socket.send_to(boost::asio::buffer(message),
+ remote_endpoint, 0, ignored_error);
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/daytime6/server.cpp b/src/boost/libs/asio/example/cpp03/tutorial/daytime6/server.cpp
new file mode 100644
index 000000000..df1f2fa47
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/daytime6/server.cpp
@@ -0,0 +1,89 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/asio.hpp>
+
+using boost::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(boost::asio::io_context& io_context)
+ : socket_(io_context, udp::endpoint(udp::v4(), 13))
+ {
+ start_receive();
+ }
+
+private:
+ void start_receive()
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(recv_buffer_), remote_endpoint_,
+ boost::bind(&udp_server::handle_receive, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+ void handle_receive(const boost::system::error_code& error,
+ std::size_t /*bytes_transferred*/)
+ {
+ if (!error)
+ {
+ boost::shared_ptr<std::string> message(
+ new std::string(make_daytime_string()));
+
+ socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
+ boost::bind(&udp_server::handle_send, this, message,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+
+ start_receive();
+ }
+ }
+
+ void handle_send(boost::shared_ptr<std::string> /*message*/,
+ const boost::system::error_code& /*error*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ }
+
+ udp::socket socket_;
+ udp::endpoint remote_endpoint_;
+ boost::array<char, 1> recv_buffer_;
+};
+
+int main()
+{
+ try
+ {
+ boost::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/src/boost/libs/asio/example/cpp03/tutorial/daytime7/server.cpp b/src/boost/libs/asio/example/cpp03/tutorial/daytime7/server.cpp
new file mode 100644
index 000000000..f52b25754
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/daytime7/server.cpp
@@ -0,0 +1,160 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/array.hpp>
+#include <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+using boost::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 boost::enable_shared_from_this<tcp_connection>
+{
+public:
+ typedef boost::shared_ptr<tcp_connection> pointer;
+
+ static pointer create(boost::asio::io_context& io_context)
+ {
+ return pointer(new tcp_connection(io_context));
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ message_ = make_daytime_string();
+
+ boost::asio::async_write(socket_, boost::asio::buffer(message_),
+ boost::bind(&tcp_connection::handle_write, shared_from_this()));
+ }
+
+private:
+ tcp_connection(boost::asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ void handle_write()
+ {
+ }
+
+ tcp::socket socket_;
+ std::string message_;
+};
+
+class tcp_server
+{
+public:
+ tcp_server(boost::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(),
+ boost::bind(&tcp_server::handle_accept, this, new_connection,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(tcp_connection::pointer new_connection,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_connection->start();
+ }
+
+ start_accept();
+ }
+
+ boost::asio::io_context& io_context_;
+ tcp::acceptor acceptor_;
+};
+
+class udp_server
+{
+public:
+ udp_server(boost::asio::io_context& io_context)
+ : socket_(io_context, udp::endpoint(udp::v4(), 13))
+ {
+ start_receive();
+ }
+
+private:
+ void start_receive()
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(recv_buffer_), remote_endpoint_,
+ boost::bind(&udp_server::handle_receive, this,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_receive(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ boost::shared_ptr<std::string> message(
+ new std::string(make_daytime_string()));
+
+ socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
+ boost::bind(&udp_server::handle_send, this, message));
+
+ start_receive();
+ }
+ }
+
+ void handle_send(boost::shared_ptr<std::string> /*message*/)
+ {
+ }
+
+ udp::socket socket_;
+ udp::endpoint remote_endpoint_;
+ boost::array<char, 1> recv_buffer_;
+};
+
+int main()
+{
+ try
+ {
+ boost::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/src/boost/libs/asio/example/cpp03/tutorial/daytime_dox.txt b/src/boost/libs/asio/example/cpp03/tutorial/daytime_dox.txt
new file mode 100644
index 000000000..5ec49c67c
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/daytime_dox.txt
@@ -0,0 +1,500 @@
+//
+// Copyright (c) 2003-2020 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)
+//
+
+/**
+\page tutdaytime1 Daytime.1 - A synchronous TCP daytime client
+
+This tutorial program shows how to use asio to implement a client application
+with TCP.
+
+\dontinclude daytime1/client.cpp
+\skip #include
+
+We start by including the necessary header files.
+
+\until asio.hpp
+
+The purpose of this application is to access a daytime service,
+so we need the user to specify the server.
+
+\until }
+
+All programs that use asio need to have at least one boost::asio::io_context
+object.
+
+\until boost::asio::io_context
+
+We need to turn the server name that was specified as a parameter to the
+application, into a TCP endpoint. To do this we use an
+boost::asio::ip::tcp::resolver object.
+
+\until tcp::resolver
+
+A resolver takes a host name and service name and turns them into a list of
+endpoints. We perform a resolve call using the name of the server, specified in
+<tt>argv[1]</tt>, and the name of the service, in this case <tt>"daytime"</tt>.
+
+The list of endpoints is returned using an object of type
+boost::asio::ip::tcp::resolver::results_type. This object is a range, with begin() and
+end() member functions that may be used for iterating over the results.
+
+\until resolver.resolve
+
+Now we create and connect the socket. The list of endpoints obtained above may
+contain both IPv4 and IPv6 endpoints, so we need to try each of them until we
+find one that works. This keeps the client program independent of a specific IP
+version. The boost::asio::connect() function does this for us automatically.
+
+\until boost::asio::connect
+
+The connection is open. All we need to do now is read the response from the
+daytime service.
+
+We use a <tt>boost::array</tt> to hold the received data. The boost::asio::buffer()
+function automatically determines the size of the array to help prevent buffer
+overruns. Instead of a <tt>boost::array</tt>, we could have used a <tt>char
+[]</tt> or <tt>std::vector</tt>.
+
+\until read_some
+
+When the server closes the connection, the boost::asio::ip::tcp::socket::read_some()
+function will exit with the boost::asio::error::eof error, which is how we know to
+exit the loop.
+
+\until }
+
+Finally, handle any exceptions that may have been thrown.
+
+\until }
+\until }
+
+See the \ref tutdaytime1src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Next: \ref tutdaytime2
+
+*/
+
+/**
+\page tutdaytime1src Source listing for Daytime.1
+\include daytime1/client.cpp
+Return to \ref tutdaytime1
+*/
+
+/**
+\page tutdaytime2 Daytime.2 - A synchronous TCP daytime server
+
+This tutorial program shows how to use asio to implement a server application
+with TCP.
+
+\dontinclude daytime2/server.cpp
+\skip #include
+
+\until using
+
+We define the function <tt>make_daytime_string()</tt> to create the string to
+be sent back to the client. This function will be reused in all of our daytime
+server applications.
+
+\until boost::asio::io_context
+
+A boost::asio::ip::tcp::acceptor object needs to be created to listen
+for new connections. It is initialised to listen on TCP port 13, for IP version 4.
+
+\until tcp::acceptor
+
+This is an iterative server, which means that it will handle one
+connection at a time. Create a socket that will represent the connection to the
+client, and then wait for a connection.
+
+\until acceptor.accept
+
+A client is accessing our service. Determine the current time
+and transfer this information to the client.
+
+\until }
+\until }
+
+Finally, handle any exceptions.
+
+\until }
+\until }
+
+See the \ref tutdaytime2src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime1 \n
+Next: \ref tutdaytime3
+
+*/
+
+/**
+\page tutdaytime2src Source listing for Daytime.2
+\include daytime2/server.cpp
+Return to \ref tutdaytime2
+*/
+
+/**
+\page tutdaytime3 Daytime.3 - An asynchronous TCP daytime server
+
+\section tutdaytime3funcmain The main() function
+
+\dontinclude daytime3/server.cpp
+\skip int main()
+\until try
+\until {
+
+We need to create a server object to accept incoming client connections. The
+boost::asio::io_context object provides I/O services, such as sockets, that the
+server object will use.
+
+\until tcp_server
+
+Run the boost::asio::io_context object so that it will perform asynchronous operations
+on your behalf.
+
+\until return 0;
+\until }
+
+\section tutdaytime3classtcp_server The tcp_server class
+
+\dontinclude daytime3/server.cpp
+\skip class tcp_server
+\until public:
+
+The constructor initialises an acceptor to listen on TCP port 13.
+
+\until private:
+
+The function <tt>start_accept()</tt> creates a socket and initiates an
+asynchronous accept operation to wait for a new connection.
+
+\until }
+
+The function <tt>handle_accept()</tt> is called when the asynchronous accept
+operation initiated by <tt>start_accept()</tt> finishes. It services the client
+request, and then calls <tt>start_accept()</tt> to initiate the next accept
+operation.
+
+\until }
+\until }
+
+\section tutdaytime3classtcp_connection The tcp_connection class
+
+We will use <tt>shared_ptr</tt> and <tt>enable_shared_from_this</tt> because we
+want to keep the <tt>tcp_connection</tt> object alive as long as there is an
+operation that refers to it.
+
+\dontinclude daytime3/server.cpp
+\skip class tcp_connection
+\until shared_ptr
+\until }
+\until }
+
+In the function <tt>start()</tt>, we call boost::asio::async_write() to serve the data
+to the client. Note that we are using boost::asio::async_write(), rather than
+boost::asio::ip::tcp::socket::async_write_some(), to ensure that the entire block of
+data is sent.
+
+\until {
+
+The data to be sent is stored in the class member <tt>message_</tt> as we need
+to keep the data valid until the asynchronous operation is complete.
+
+\until message_
+
+When initiating the asynchronous operation, and if using boost::bind(), you
+must specify only the arguments that match the handler's parameter list. In
+this program, both of the argument placeholders (boost::asio::placeholders::error and
+boost::asio::placeholders::bytes_transferred) could potentially have been removed,
+since they are not being used in <tt>handle_write()</tt>.
+
+\until placeholders::bytes_transferred
+
+Any further actions for this client connection are now the responsibility of
+<tt>handle_write()</tt>.
+
+\until };
+
+\section tutdaytime3remunused Removing unused handler parameters
+
+You may have noticed that the <tt>error</tt>, and <tt>bytes_transferred</tt>
+parameters are not used in the body of the <tt>handle_write()</tt> function. If
+parameters are not needed, it is possible to remove them from the function so
+that it looks like:
+
+\code
+ void handle_write()
+ {
+ }
+\endcode
+
+The boost::asio::async_write() call used to initiate the call can then be changed to
+just:
+
+\code
+ boost::asio::async_write(socket_, boost::asio::buffer(message_),
+ boost::bind(&tcp_connection::handle_write, shared_from_this()));
+\endcode
+
+See the \ref tutdaytime3src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime2 \n
+Next: \ref tutdaytime4
+
+*/
+
+/**
+\page tutdaytime3src Source listing for Daytime.3
+\include daytime3/server.cpp
+Return to \ref tutdaytime3
+*/
+
+/**
+\page tutdaytime4 Daytime.4 - A synchronous UDP daytime client
+
+This tutorial program shows how to use asio to implement a client application
+with UDP.
+
+\dontinclude daytime4/client.cpp
+\skip #include
+\until using boost::asio::ip::udp;
+
+The start of the application is essentially the same as for the TCP daytime
+client.
+
+\until boost::asio::io_context
+
+We use an boost::asio::ip::udp::resolver object to find the correct remote endpoint to
+use based on the host and service names. The query is restricted to return only
+IPv4 endpoints by the boost::asio::ip::udp::v4() argument.
+
+\until udp::v4
+
+The boost::asio::ip::udp::resolver::resolve() function is guaranteed to return at
+least one endpoint in the list if it does not fail. This means it is safe to
+dereference the return value directly.
+
+\until udp::endpoint
+
+Since UDP is datagram-oriented, we will not be using a stream socket. Create an
+boost::asio::ip::udp::socket and initiate contact with the remote endpoint.
+
+\until receiver_endpoint
+
+Now we need to be ready to accept whatever the server sends back to us. The
+endpoint on our side that receives the server's response will be initialised by
+boost::asio::ip::udp::socket::receive_from().
+
+\until }
+
+Finally, handle any exceptions that may have been thrown.
+
+\until }
+\until }
+See the \ref tutdaytime4src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime3 \n
+Next: \ref tutdaytime5
+
+*/
+
+/**
+\page tutdaytime4src Source listing for Daytime.4
+\include daytime4/client.cpp
+Return to \ref tutdaytime4
+*/
+
+/**
+\page tutdaytime5 Daytime.5 - A synchronous UDP daytime server
+
+This tutorial program shows how to use asio to implement a server application
+with UDP.
+
+\dontinclude daytime5/server.cpp
+\skip int main()
+\until boost::asio::io_context
+
+Create an boost::asio::ip::udp::socket object to receive requests on UDP port 13.
+
+\until udp::socket
+
+Wait for a client to initiate contact with us. The remote_endpoint object will
+be populated by boost::asio::ip::udp::socket::receive_from().
+
+\until receive_from
+
+Determine what we are going to send back to the client.
+
+\until std::string message
+
+Send the response to the remote_endpoint.
+
+\until }
+\until }
+
+Finally, handle any exceptions.
+
+\until }
+\until }
+
+See the \ref tutdaytime5src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime4 \n
+Next: \ref tutdaytime6
+
+*/
+
+/**
+\page tutdaytime5src Source listing for Daytime.5
+\include daytime5/server.cpp
+Return to \ref tutdaytime5
+*/
+
+/**
+\page tutdaytime6 Daytime.6 - An asynchronous UDP daytime server
+
+\section tutdaytime6funcmain The main() function
+
+\dontinclude daytime6/server.cpp
+\skip int main()
+\until try
+\until {
+
+Create a server object to accept incoming client requests, and run
+the boost::asio::io_context object.
+
+\until return 0;
+\until }
+
+\section tutdaytime6classudp_server The udp_server class
+
+\dontinclude daytime6/server.cpp
+\skip class udp_server
+\until public:
+
+The constructor initialises a socket to listen on UDP port 13.
+
+\until private:
+\until {
+
+The function boost::asio::ip::udp::socket::async_receive_from() will cause the
+application to listen in the background for a new request. When such a request
+is received, the boost::asio::io_context object will invoke the
+<tt>handle_receive()</tt> function with two arguments: a value of type
+boost::system::error_code indicating whether the operation succeeded or failed, and a
+<tt>size_t</tt> value <tt>bytes_transferred</tt> specifying the number of bytes
+received.
+
+\until }
+
+The function <tt>handle_receive()</tt> will service the client request.
+
+\until {
+
+The <tt>error</tt> parameter contains the result of the asynchronous operation.
+Since we only provide the 1-byte <tt>recv_buffer_</tt> to contain the client's
+request, the boost::asio::io_context object would return an error if the client sent
+anything larger. We can ignore such an error if it comes up.
+
+\until {
+
+Determine what we are going to send.
+
+\until make_daytime_string()
+
+We now call boost::asio::ip::udp::socket::async_send_to() to serve the data to the
+client.
+
+\until boost::asio::placeholders::bytes_transferred
+
+When initiating the asynchronous operation, and if using boost::bind(), you
+must specify only the arguments that match the handler's parameter list. In
+this program, both of the argument placeholders (boost::asio::placeholders::error and
+boost::asio::placeholders::bytes_transferred) could potentially have been removed.
+
+Start listening for the next client request.
+
+\until start_receive
+
+Any further actions for this client request are now the responsibility of
+<tt>handle_send()</tt>.
+
+\until }
+\until }
+
+The function <tt>handle_send()</tt> is invoked after the service request has
+been completed.
+
+\until }
+\until }
+
+See the \ref tutdaytime6src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime5 \n
+Next: \ref tutdaytime7
+
+*/
+
+/**
+\page tutdaytime6src Source listing for Daytime.6
+\include daytime6/server.cpp
+Return to \ref tutdaytime6
+*/
+
+/**
+\page tutdaytime7 Daytime.7 - A combined TCP/UDP asynchronous server
+
+This tutorial program shows how to combine the two asynchronous servers that we
+have just written, into a single server application.
+
+\section tutdaytime7funcmain The main() function
+
+\dontinclude daytime7/server.cpp
+\skip int main()
+\until boost::asio::io_context
+
+We will begin by creating a server object to accept a TCP client connection.
+
+\until tcp_server
+
+We also need a server object to accept a UDP client request.
+
+\until udp_server
+
+We have created two lots of work for the boost::asio::io_context object to do.
+
+\until return 0;
+\until }
+
+\section tutdaytime7classtcp The tcp_connection and tcp_server classes
+
+The following two classes are taken from \ref tutdaytime3 "Daytime.3".
+
+\dontinclude daytime7/server.cpp
+\skip class tcp_connection
+\until };
+\until };
+
+\section tutdaytime7classudp The udp_server class
+
+Similarly, this next class is taken from the
+\ref tutdaytime6 "previous tutorial step".
+
+\dontinclude daytime7/server.cpp
+\skip class udp_server
+\until };
+
+See the \ref tutdaytime7src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime6
+
+*/
+
+/**
+\page tutdaytime7src Source listing for Daytime.7
+\include daytime7/server.cpp
+Return to \ref tutdaytime7
+*/
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/index_dox.txt b/src/boost/libs/asio/example/cpp03/tutorial/index_dox.txt
new file mode 100644
index 000000000..a57c0f2d3
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/index_dox.txt
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2003-2020 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)
+//
+
+/**
+\mainpage asio Tutorial
+
+\section tuttimer Basic Skills
+
+The tutorial programs in this first section introduce the fundamental concepts
+required to use the asio toolkit. Before plunging into the complex world of
+network programming, these tutorial programs illustrate the basic skills using
+simple asynchronous timers.
+
+\li \ref tuttimer1
+\li \ref tuttimer2
+\li \ref tuttimer3
+\li \ref tuttimer4
+\li \ref tuttimer5
+
+\section tutdaytime Introduction to Sockets
+
+The tutorial programs in this section show how to use asio to develop simple
+client and server programs. These tutorial programs are based around the <a
+href="http://www.ietf.org/rfc/rfc867.txt">daytime</a> protocol, which supports
+both TCP and UDP.
+
+The first three tutorial programs implement the daytime protocol using TCP.
+
+\li \ref tutdaytime1
+\li \ref tutdaytime2
+\li \ref tutdaytime3
+
+The next three tutorial programs implement the daytime protocol using UDP.
+
+\li \ref tutdaytime4
+\li \ref tutdaytime5
+\li \ref tutdaytime6
+
+The last tutorial program in this section demonstrates how asio allows the TCP
+and UDP servers to be easily combined into a single program.
+
+\li \ref tutdaytime7
+
+*/
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/timer1/timer.cpp b/src/boost/libs/asio/example/cpp03/tutorial/timer1/timer.cpp
new file mode 100644
index 000000000..77906d15a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/timer1/timer.cpp
@@ -0,0 +1,24 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+
+int main()
+{
+ boost::asio::io_context io;
+
+ boost::asio::steady_timer t(io, boost::asio::chrono::seconds(5));
+ t.wait();
+
+ std::cout << "Hello, world!" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/timer2/timer.cpp b/src/boost/libs/asio/example/cpp03/tutorial/timer2/timer.cpp
new file mode 100644
index 000000000..030910b51
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/timer2/timer.cpp
@@ -0,0 +1,29 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+
+void print(const boost::system::error_code& /*e*/)
+{
+ std::cout << "Hello, world!" << std::endl;
+}
+
+int main()
+{
+ boost::asio::io_context io;
+
+ boost::asio::steady_timer t(io, boost::asio::chrono::seconds(5));
+ t.async_wait(&print);
+
+ io.run();
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/timer3/timer.cpp b/src/boost/libs/asio/example/cpp03/tutorial/timer3/timer.cpp
new file mode 100644
index 000000000..44c9044de
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/timer3/timer.cpp
@@ -0,0 +1,43 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+
+void print(const boost::system::error_code& /*e*/,
+ boost::asio::steady_timer* t, int* count)
+{
+ if (*count < 5)
+ {
+ std::cout << *count << std::endl;
+ ++(*count);
+
+ t->expires_at(t->expiry() + boost::asio::chrono::seconds(1));
+ t->async_wait(boost::bind(print,
+ boost::asio::placeholders::error, t, count));
+ }
+}
+
+int main()
+{
+ boost::asio::io_context io;
+
+ int count = 0;
+ boost::asio::steady_timer t(io, boost::asio::chrono::seconds(1));
+ t.async_wait(boost::bind(print,
+ boost::asio::placeholders::error, &t, &count));
+
+ io.run();
+
+ std::cout << "Final count is " << count << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/timer4/timer.cpp b/src/boost/libs/asio/example/cpp03/tutorial/timer4/timer.cpp
new file mode 100644
index 000000000..afcdcb396
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/timer4/timer.cpp
@@ -0,0 +1,54 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+
+class printer
+{
+public:
+ printer(boost::asio::io_context& io)
+ : timer_(io, boost::asio::chrono::seconds(1)),
+ count_(0)
+ {
+ timer_.async_wait(boost::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() + boost::asio::chrono::seconds(1));
+ timer_.async_wait(boost::bind(&printer::print, this));
+ }
+ }
+
+private:
+ boost::asio::steady_timer timer_;
+ int count_;
+};
+
+int main()
+{
+ boost::asio::io_context io;
+ printer p(io);
+ io.run();
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/timer5/timer.cpp b/src/boost/libs/asio/example/cpp03/tutorial/timer5/timer.cpp
new file mode 100644
index 000000000..b5d48f8e2
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/timer5/timer.cpp
@@ -0,0 +1,81 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/bind/bind.hpp>
+
+class printer
+{
+public:
+ printer(boost::asio::io_context& io)
+ : strand_(boost::asio::make_strand(io)),
+ timer1_(io, boost::asio::chrono::seconds(1)),
+ timer2_(io, boost::asio::chrono::seconds(1)),
+ count_(0)
+ {
+ timer1_.async_wait(boost::asio::bind_executor(strand_,
+ boost::bind(&printer::print1, this)));
+
+ timer2_.async_wait(boost::asio::bind_executor(strand_,
+ boost::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() + boost::asio::chrono::seconds(1));
+
+ timer1_.async_wait(boost::asio::bind_executor(strand_,
+ boost::bind(&printer::print1, this)));
+ }
+ }
+
+ void print2()
+ {
+ if (count_ < 10)
+ {
+ std::cout << "Timer 2: " << count_ << std::endl;
+ ++count_;
+
+ timer2_.expires_at(timer2_.expiry() + boost::asio::chrono::seconds(1));
+
+ timer2_.async_wait(boost::asio::bind_executor(strand_,
+ boost::bind(&printer::print2, this)));
+ }
+ }
+
+private:
+ boost::asio::strand<boost::asio::io_context::executor_type> strand_;
+ boost::asio::steady_timer timer1_;
+ boost::asio::steady_timer timer2_;
+ int count_;
+};
+
+int main()
+{
+ boost::asio::io_context io;
+ printer p(io);
+ boost::thread t(boost::bind(&boost::asio::io_context::run, &io));
+ io.run();
+ t.join();
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp03/tutorial/timer_dox.txt b/src/boost/libs/asio/example/cpp03/tutorial/timer_dox.txt
new file mode 100644
index 000000000..fdf7fb186
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/tutorial/timer_dox.txt
@@ -0,0 +1,378 @@
+//
+// Copyright (c) 2003-2020 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)
+//
+
+/**
+\page tuttimer1 Timer.1 - Using a timer synchronously
+
+This tutorial program introduces asio by showing how to perform a blocking
+wait on a timer.
+
+\dontinclude timer1/timer.cpp
+\skip #include
+
+We start by including the necessary header files.
+
+All of the asio classes can be used by simply including the <tt>"asio.hpp"</tt>
+header file.
+
+\until asio.hpp
+
+All programs that use asio need to have at least one boost::asio::io_context object.
+This class provides access to I/O functionality. We declare an object of this
+type first thing in the main function.
+
+\until boost::asio::io_context
+
+Next we declare an object of type boost::asio::steady_timer. The core asio classes
+that provide I/O functionality (or as in this case timer functionality) always
+take a reference to an io_context as their first constructor argument. The
+second argument to the constructor sets the timer to expire 5 seconds from now.
+
+\until boost::asio::steady_timer
+
+In this simple example we perform a blocking wait on the timer.
+That is, the call to boost::asio::steady_timer::wait() will not return until the
+timer has expired, 5 seconds after it was created (i.e. <b>not</b> from when the
+wait starts).
+
+A timer is always in one of two states: "expired" or "not expired". If the
+boost::asio::steady_timer::wait() function is called on an expired timer, it will
+return immediately.
+
+\until wait
+
+Finally we print the obligatory <tt>"Hello, world!"</tt>
+message to show when the timer has expired.
+
+\until }
+
+See the \ref tuttimer1src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Next: \ref tuttimer2
+
+*/
+
+/**
+\page tuttimer1src Source listing for Timer.1
+\include timer1/timer.cpp
+Return to \ref tuttimer1
+*/
+
+/**
+\page tuttimer2 Timer.2 - Using a timer asynchronously
+
+This tutorial program demonstrates how to use asio's asynchronous callback
+functionality by modifying the program from tutorial Timer.1 to perform an
+asynchronous wait on the timer.
+
+\dontinclude timer2/timer.cpp
+\skip #include
+
+\until asio.hpp
+
+Using asio's asynchronous functionality means having a callback
+function that will be called when an asynchronous operation completes. In this
+program we define a function called <tt>print</tt> to be called when the
+asynchronous wait finishes.
+
+\until boost::asio::steady_timer
+
+Next, instead of doing a blocking wait as in tutorial Timer.1,
+we call the boost::asio::steady_timer::async_wait() function to perform an
+asynchronous wait. When calling this function we pass the <tt>print</tt>
+callback handler that was defined above.
+
+\skipline async_wait
+
+Finally, we must call the boost::asio::io_context::run() member function
+on the io_context object.
+
+The asio library provides a guarantee that callback handlers will <b>only</b>
+be called from threads that are currently calling boost::asio::io_context::run().
+Therefore unless the boost::asio::io_context::run() function is called the callback for
+the asynchronous wait completion will never be invoked.
+
+The boost::asio::io_context::run() function will also continue to run while there is
+still "work" to do. In this example, the work is the asynchronous wait on the
+timer, so the call will not return until the timer has expired and the
+callback has completed.
+
+It is important to remember to give the io_context some work to do before
+calling boost::asio::io_context::run(). For example, if we had omitted the above call
+to boost::asio::steady_timer::async_wait(), the io_context would not have had any
+work to do, and consequently boost::asio::io_context::run() would have returned
+immediately.
+
+\skip run
+\until }
+
+See the \ref tuttimer2src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tuttimer1 \n
+Next: \ref tuttimer3
+
+*/
+
+/**
+\page tuttimer2src Source listing for Timer.2
+\include timer2/timer.cpp
+Return to \ref tuttimer2
+*/
+
+/**
+\page tuttimer3 Timer.3 - Binding arguments to a handler
+
+In this tutorial we will modify the program from tutorial Timer.2 so that the
+timer fires once a second. This will show how to pass additional parameters to
+your handler function.
+
+\dontinclude timer3/timer.cpp
+\skip #include
+
+\until bind.hpp
+
+To implement a repeating timer using asio you need to change
+the timer's expiry time in your callback function, and to then start a new
+asynchronous wait. Obviously this means that the callback function will need
+to be able to access the timer object. To this end we add two new parameters
+to the <tt>print</tt> function:
+
+\li A pointer to a timer object.
+
+\li A counter so that we can stop the program when the timer fires for the
+sixth time.
+
+\until {
+
+As mentioned above, this tutorial program uses a counter to
+stop running when the timer fires for the sixth time. However you will observe
+that there is no explicit call to ask the io_context to stop. Recall that in
+tutorial Timer.2 we learnt that the boost::asio::io_context::run() function completes
+when there is no more "work" to do. By not starting a new asynchronous wait on
+the timer when <tt>count</tt> reaches 5, the io_context will run out of work and
+stop running.
+
+\until ++
+
+Next we move the expiry time for the timer along by one second
+from the previous expiry time. By calculating the new expiry time relative to
+the old, we can ensure that the timer does not drift away from the
+whole-second mark due to any delays in processing the handler.
+
+\until expires_at
+
+Then we start a new asynchronous wait on the timer. As you can
+see, the boost::bind() function is used to associate the extra parameters
+with your callback handler. The boost::asio::steady_timer::async_wait() function
+expects a handler function (or function object) with the signature
+<tt>void(const boost::system::error_code&)</tt>. Binding the additional parameters
+converts your <tt>print</tt> function into a function object that matches the
+signature correctly.
+
+See the <a href="http://www.boost.org/libs/bind/bind.html">Boost.Bind
+documentation</a> for more information on how to use boost::bind().
+
+In this example, the boost::asio::placeholders::error argument to boost::bind() is a
+named placeholder for the error object passed to the handler. When initiating
+the asynchronous operation, and if using boost::bind(), you must specify only
+the arguments that match the handler's parameter list. In tutorial Timer.4 you
+will see that this placeholder may be elided if the parameter is not needed by
+the callback handler.
+
+\until boost::asio::io_context
+
+A new <tt>count</tt> variable is added so that we can stop the
+program when the timer fires for the sixth time.
+
+\until boost::asio::steady_timer
+
+As in Step 4, when making the call to
+boost::asio::steady_timer::async_wait() from <tt>main</tt> we bind the additional
+parameters needed for the <tt>print</tt> function.
+
+\until run
+
+Finally, just to prove that the <tt>count</tt> variable was
+being used in the <tt>print</tt> handler function, we will print out its new
+value.
+
+\until }
+
+See the \ref tuttimer3src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tuttimer2 \n
+Next: \ref tuttimer4
+
+*/
+
+/**
+\page tuttimer3src Source listing for Timer.3
+\include timer3/timer.cpp
+Return to \ref tuttimer3
+*/
+
+/**
+\page tuttimer4 Timer.4 - Using a member function as a handler
+
+In this tutorial we will see how to use a class member function as a callback
+handler. The program should execute identically to the tutorial program from
+tutorial Timer.3.
+
+\dontinclude timer4/timer.cpp
+\skip #include
+
+\until bind.hpp
+
+Instead of defining a free function <tt>print</tt> as the
+callback handler, as we did in the earlier tutorial programs, we now define a
+class called <tt>printer</tt>.
+
+\until public
+
+The constructor of this class will take a reference to the
+io_context object and use it when initialising the <tt>timer_</tt> member. The
+counter used to shut down the program is now also a member of the class.
+
+\until {
+
+The boost::bind() function works just as well with class
+member functions as with free functions. Since all non-static class member
+functions have an implicit <tt>this</tt> parameter, we need to bind
+<tt>this</tt> to the function. As in tutorial Timer.3, boost::bind()
+converts our callback handler (now a member function) into a function object
+that can be invoked as though it has the signature <tt>void(const
+boost::system::error_code&)</tt>.
+
+You will note that the boost::asio::placeholders::error placeholder is not specified
+here, as the <tt>print</tt> member function does not accept an error object as
+a parameter.
+
+\until }
+
+In the class destructor we will print out the final value of
+the counter.
+
+\until }
+
+The <tt>print</tt> member function is very similar to the
+<tt>print</tt> function from tutorial Timer.3, except that it now operates on
+the class data members instead of having the timer and counter passed in as
+parameters.
+
+\until };
+
+The <tt>main</tt> function is much simpler than before, as it
+now declares a local <tt>printer</tt> object before running the io_context as
+normal.
+
+\until }
+
+See the \ref tuttimer4src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tuttimer3 \n
+Next: \ref tuttimer5 \n
+
+*/
+
+/**
+\page tuttimer4src Source listing for Timer.4
+\include timer4/timer.cpp
+Return to \ref tuttimer4
+*/
+
+/**
+\page tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs
+
+This tutorial demonstrates the use of the boost::asio::strand class template to
+synchronise callback handlers in a multithreaded program.
+
+The previous four tutorials avoided the issue of handler synchronisation by
+calling the boost::asio::io_context::run() function from one thread only. As you
+already know, the asio library provides a guarantee that callback handlers will
+<b>only</b> be called from threads that are currently calling
+boost::asio::io_context::run(). Consequently, calling boost::asio::io_context::run() from
+only one thread ensures that callback handlers cannot run concurrently.
+
+The single threaded approach is usually the best place to start when
+developing applications using asio. The downside is the limitations it places
+on programs, particularly servers, including:
+
+<ul>
+<li>Poor responsiveness when handlers can take a long time to complete.</li>
+<li>An inability to scale on multiprocessor systems.</li>
+</ul>
+
+If you find yourself running into these limitations, an alternative approach
+is to have a pool of threads calling boost::asio::io_context::run(). However, as this
+allows handlers to execute concurrently, we need a method of synchronisation
+when handlers might be accessing a shared, thread-unsafe resource.
+
+\dontinclude timer5/timer.cpp
+\skip #include
+
+\until bind.hpp
+
+We start by defining a class called <tt>printer</tt>, similar
+to the class in the previous tutorial. This class will extend the previous
+tutorial by running two timers in parallel.
+
+\until public
+
+In addition to initialising a pair of boost::asio::steady_timer members, the
+constructor initialises the <tt>strand_</tt> member, an object of type
+boost::asio::strand<boost::asio::io_context::executor_type>.
+
+The boost::asio::strand class template is an executor adapter that guarantees
+that, for those handlers that are dispatched through it, an executing handler
+will be allowed to complete before the next one is started. This is guaranteed
+irrespective of the number of threads that are calling
+boost::asio::io_context::run(). Of course, the handlers may still execute
+concurrently with other handlers that were <b>not</b> dispatched through an
+boost::asio::strand, or were dispatched through a different boost::asio::strand
+object.
+
+\until {
+
+When initiating the asynchronous operations, each callback handler is "bound"
+to an boost::asio::strand<boost::asio::io_context::executor_type> object. The
+boost::asio::bind_executor() function returns a new handler that automatically
+dispatches its contained handler through the boost::asio::strand object. By
+binding the handlers to the same boost::asio::strand, we are ensuring that they
+cannot execute concurrently.
+
+\until }
+\until }
+
+In a multithreaded program, the handlers for asynchronous
+operations should be synchronised if they access shared resources. In this
+tutorial, the shared resources used by the handlers (<tt>print1</tt> and
+<tt>print2</tt>) are <tt>std::cout</tt> and the <tt>count_</tt> data member.
+
+\until };
+
+The <tt>main</tt> function now causes boost::asio::io_context::run() to
+be called from two threads: the main thread and one additional thread. This is
+accomplished using an boost::thread object.
+
+Just as it would with a call from a single thread, concurrent calls to
+boost::asio::io_context::run() will continue to execute while there is "work" left to
+do. The background thread will not exit until all asynchronous operations have
+completed.
+
+\until }
+
+See the \ref tuttimer5src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tuttimer4 \n
+
+*/
+
+/**
+\page tuttimer5src Source listing for Timer.5
+\include timer5/timer.cpp
+Return to \ref tuttimer5
+*/
diff --git a/src/boost/libs/asio/example/cpp03/windows/Jamfile.v2 b/src/boost/libs/asio/example/cpp03/windows/Jamfile.v2
new file mode 100644
index 000000000..c34228303
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/windows/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe transmit_file
+ : transmit_file.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp03/windows/transmit_file.cpp b/src/boost/libs/asio/example/cpp03/windows/transmit_file.cpp
new file mode 100644
index 000000000..a544eb904
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp03/windows/transmit_file.cpp
@@ -0,0 +1,177 @@
+//
+// transmit_file.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/bind/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/asio.hpp>
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
+
+using boost::asio::ip::tcp;
+using boost::asio::windows::overlapped_ptr;
+using boost::asio::windows::random_access_handle;
+
+typedef boost::asio::basic_stream_socket<tcp,
+ boost::asio::io_context::executor_type> tcp_socket;
+
+typedef boost::asio::basic_socket_acceptor<tcp,
+ boost::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.
+ boost::system::error_code ec(last_error,
+ boost::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 boost::enable_shared_from_this<connection>
+{
+public:
+ typedef boost::shared_ptr<connection> pointer;
+
+ static pointer create(boost::asio::io_context& io_context,
+ const std::string& filename)
+ {
+ return pointer(new connection(io_context, filename));
+ }
+
+ tcp_socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ boost::system::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_,
+ boost::bind(&connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ }
+
+private:
+ connection(boost::asio::io_context& io_context, const std::string& filename)
+ : socket_(io_context),
+ filename_(filename),
+ file_(io_context)
+ {
+ }
+
+ void handle_write(const boost::system::error_code& /*error*/,
+ size_t /*bytes_transferred*/)
+ {
+ boost::system::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(boost::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(),
+ boost::bind(&server::handle_accept, this, new_connection,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_accept(connection::pointer new_connection,
+ const boost::system::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;
+ }
+
+ boost::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(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
+# error Overlapped I/O not available on this platform
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
diff --git a/src/boost/libs/asio/example/cpp11/allocation/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/allocation/Jamfile.v2
new file mode 100644
index 000000000..4ff960f4c
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/allocation/Jamfile.v2
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : server.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/allocation/server.cpp b/src/boost/libs/asio/example/cpp11/allocation/server.cpp
new file mode 100644
index 000000000..0edb03190
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/allocation/server.cpp
@@ -0,0 +1,255 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <iostream>
+#include <memory>
+#include <type_traits>
+#include <utility>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+// Class to manage the memory to be used for handler-based custom allocation.
+// It contains a single block of memory which may be returned for allocation
+// requests. If the memory is in use when an allocation request is made, the
+// allocator delegates allocation to the global heap.
+class handler_memory
+{
+public:
+ handler_memory()
+ : in_use_(false)
+ {
+ }
+
+ handler_memory(const handler_memory&) = delete;
+ handler_memory& operator=(const handler_memory&) = delete;
+
+ void* allocate(std::size_t size)
+ {
+ if (!in_use_ && size < sizeof(storage_))
+ {
+ in_use_ = true;
+ return &storage_;
+ }
+ else
+ {
+ return ::operator new(size);
+ }
+ }
+
+ void deallocate(void* pointer)
+ {
+ if (pointer == &storage_)
+ {
+ in_use_ = false;
+ }
+ else
+ {
+ ::operator delete(pointer);
+ }
+ }
+
+private:
+ // Storage space used for handler-based custom memory allocation.
+ typename std::aligned_storage<1024>::type storage_;
+
+ // Whether the handler-based custom allocation storage has been used.
+ bool in_use_;
+};
+
+// The allocator to be associated with the handler objects. This allocator only
+// needs to satisfy the C++11 minimal allocator requirements.
+template <typename T>
+class handler_allocator
+{
+public:
+ using value_type = T;
+
+ explicit handler_allocator(handler_memory& mem)
+ : memory_(mem)
+ {
+ }
+
+ template <typename U>
+ handler_allocator(const handler_allocator<U>& other) noexcept
+ : memory_(other.memory_)
+ {
+ }
+
+ bool operator==(const handler_allocator& other) const noexcept
+ {
+ return &memory_ == &other.memory_;
+ }
+
+ bool operator!=(const handler_allocator& other) const noexcept
+ {
+ return &memory_ != &other.memory_;
+ }
+
+ T* allocate(std::size_t n) const
+ {
+ return static_cast<T*>(memory_.allocate(sizeof(T) * n));
+ }
+
+ void deallocate(T* p, std::size_t /*n*/) const
+ {
+ return memory_.deallocate(p);
+ }
+
+private:
+ template <typename> friend class handler_allocator;
+
+ // The underlying memory.
+ 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>
+{
+public:
+ session(tcp::socket socket)
+ : socket_(std::move(socket))
+ {
+ }
+
+ void start()
+ {
+ do_read();
+ }
+
+private:
+ void do_read()
+ {
+ auto self(shared_from_this());
+ socket_.async_read_some(boost::asio::buffer(data_),
+ make_custom_alloc_handler(handler_memory_,
+ [this, self](boost::system::error_code ec, std::size_t length)
+ {
+ if (!ec)
+ {
+ do_write(length);
+ }
+ }));
+ }
+
+ void do_write(std::size_t length)
+ {
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
+ make_custom_alloc_handler(handler_memory_,
+ [this, self](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ {
+ do_read();
+ }
+ }));
+ }
+
+ // The socket used to communicate with the client.
+ tcp::socket socket_;
+
+ // Buffer used to store data received from the client.
+ std::array<char, 1024> data_;
+
+ // The memory to use for handler-based custom memory allocation.
+ handler_memory handler_memory_;
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
+ {
+ do_accept();
+ }
+
+private:
+ void do_accept()
+ {
+ acceptor_.async_accept(
+ [this](boost::system::error_code ec, tcp::socket socket)
+ {
+ if (!ec)
+ {
+ std::make_shared<session>(std::move(socket))->start();
+ }
+
+ do_accept();
+ });
+ }
+
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+ server s(io_context, std::atoi(argv[1]));
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/buffers/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/buffers/Jamfile.v2
new file mode 100644
index 000000000..f04d22493
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/buffers/Jamfile.v2
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : reference_counted.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/buffers/reference_counted.cpp b/src/boost/libs/asio/example/cpp11/buffers/reference_counted.cpp
new file mode 100644
index 000000000..7ee99d349
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/buffers/reference_counted.cpp
@@ -0,0 +1,122 @@
+//
+// reference_counted.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <iostream>
+#include <memory>
+#include <utility>
+#include <vector>
+#include <ctime>
+
+using boost::asio::ip::tcp;
+
+// A reference-counted non-modifiable buffer class.
+class shared_const_buffer
+{
+public:
+ // Construct from a std::string.
+ explicit shared_const_buffer(const std::string& data)
+ : data_(new std::vector<char>(data.begin(), data.end())),
+ buffer_(boost::asio::buffer(*data_))
+ {
+ }
+
+ // Implement the ConstBufferSequence requirements.
+ typedef boost::asio::const_buffer value_type;
+ typedef const boost::asio::const_buffer* const_iterator;
+ const boost::asio::const_buffer* begin() const { return &buffer_; }
+ const boost::asio::const_buffer* end() const { return &buffer_ + 1; }
+
+private:
+ std::shared_ptr<std::vector<char> > data_;
+ boost::asio::const_buffer buffer_;
+};
+
+class session
+ : public std::enable_shared_from_this<session>
+{
+public:
+ session(tcp::socket socket)
+ : socket_(std::move(socket))
+ {
+ }
+
+ void start()
+ {
+ do_write();
+ }
+
+private:
+ void do_write()
+ {
+ std::time_t now = std::time(0);
+ shared_const_buffer buffer(std::ctime(&now));
+
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_, buffer,
+ [self](boost::system::error_code /*ec*/, std::size_t /*length*/)
+ {
+ });
+ }
+
+ // The socket used to communicate with the client.
+ tcp::socket socket_;
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
+ {
+ do_accept();
+ }
+
+private:
+ void do_accept()
+ {
+ acceptor_.async_accept(
+ [this](boost::system::error_code ec, tcp::socket socket)
+ {
+ if (!ec)
+ {
+ std::make_shared<session>(std::move(socket))->start();
+ }
+
+ do_accept();
+ });
+ }
+
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: reference_counted <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ server s(io_context, std::atoi(argv[1]));
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/chat/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/chat/Jamfile.v2
new file mode 100644
index 000000000..1908cf7ce
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/chat/Jamfile.v2
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe chat_server : chat_server.cpp ;
+exe chat_client : chat_client.cpp ;
diff --git a/src/boost/libs/asio/example/cpp11/chat/chat_client.cpp b/src/boost/libs/asio/example/cpp11/chat/chat_client.cpp
new file mode 100644
index 000000000..c44e04fa4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/chat/chat_client.cpp
@@ -0,0 +1,167 @@
+//
+// chat_client.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <deque>
+#include <iostream>
+#include <thread>
+#include <boost/asio.hpp>
+#include "chat_message.hpp"
+
+using boost::asio::ip::tcp;
+
+typedef std::deque<chat_message> chat_message_queue;
+
+class chat_client
+{
+public:
+ chat_client(boost::asio::io_context& io_context,
+ const tcp::resolver::results_type& endpoints)
+ : io_context_(io_context),
+ socket_(io_context)
+ {
+ do_connect(endpoints);
+ }
+
+ void write(const chat_message& msg)
+ {
+ boost::asio::post(io_context_,
+ [this, msg]()
+ {
+ bool write_in_progress = !write_msgs_.empty();
+ write_msgs_.push_back(msg);
+ if (!write_in_progress)
+ {
+ do_write();
+ }
+ });
+ }
+
+ void close()
+ {
+ boost::asio::post(io_context_, [this]() { socket_.close(); });
+ }
+
+private:
+ void do_connect(const tcp::resolver::results_type& endpoints)
+ {
+ boost::asio::async_connect(socket_, endpoints,
+ [this](boost::system::error_code ec, tcp::endpoint)
+ {
+ if (!ec)
+ {
+ do_read_header();
+ }
+ });
+ }
+
+ void do_read_header()
+ {
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ [this](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec && read_msg_.decode_header())
+ {
+ do_read_body();
+ }
+ else
+ {
+ socket_.close();
+ }
+ });
+ }
+
+ void do_read_body()
+ {
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
+ [this](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ {
+ std::cout.write(read_msg_.body(), read_msg_.body_length());
+ std::cout << "\n";
+ do_read_header();
+ }
+ else
+ {
+ socket_.close();
+ }
+ });
+ }
+
+ void do_write()
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msgs_.front().data(),
+ write_msgs_.front().length()),
+ [this](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ {
+ write_msgs_.pop_front();
+ if (!write_msgs_.empty())
+ {
+ do_write();
+ }
+ }
+ else
+ {
+ socket_.close();
+ }
+ });
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ tcp::socket socket_;
+ chat_message read_msg_;
+ chat_message_queue write_msgs_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: chat_client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ tcp::resolver resolver(io_context);
+ auto endpoints = resolver.resolve(argv[1], argv[2]);
+ chat_client c(io_context, endpoints);
+
+ std::thread t([&io_context](){ io_context.run(); });
+
+ char line[chat_message::max_body_length + 1];
+ while (std::cin.getline(line, chat_message::max_body_length + 1))
+ {
+ chat_message msg;
+ msg.body_length(std::strlen(line));
+ std::memcpy(msg.body(), line, msg.body_length());
+ msg.encode_header();
+ c.write(msg);
+ }
+
+ c.close();
+ t.join();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/chat/chat_message.hpp b/src/boost/libs/asio/example/cpp11/chat/chat_message.hpp
new file mode 100644
index 000000000..9507f6ae9
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/chat/chat_message.hpp
@@ -0,0 +1,91 @@
+//
+// chat_message.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 CHAT_MESSAGE_HPP
+#define CHAT_MESSAGE_HPP
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+class chat_message
+{
+public:
+ enum { header_length = 4 };
+ enum { max_body_length = 512 };
+
+ chat_message()
+ : body_length_(0)
+ {
+ }
+
+ const char* data() const
+ {
+ return data_;
+ }
+
+ char* data()
+ {
+ return data_;
+ }
+
+ std::size_t length() const
+ {
+ return header_length + body_length_;
+ }
+
+ const char* body() const
+ {
+ return data_ + header_length;
+ }
+
+ char* body()
+ {
+ return data_ + header_length;
+ }
+
+ std::size_t body_length() const
+ {
+ return body_length_;
+ }
+
+ void body_length(std::size_t new_length)
+ {
+ body_length_ = new_length;
+ if (body_length_ > max_body_length)
+ body_length_ = max_body_length;
+ }
+
+ bool decode_header()
+ {
+ char header[header_length + 1] = "";
+ std::strncat(header, data_, header_length);
+ body_length_ = std::atoi(header);
+ if (body_length_ > max_body_length)
+ {
+ body_length_ = 0;
+ return false;
+ }
+ return true;
+ }
+
+ void encode_header()
+ {
+ char header[header_length + 1] = "";
+ std::sprintf(header, "%4d", static_cast<int>(body_length_));
+ std::memcpy(data_, header, header_length);
+ }
+
+private:
+ char data_[header_length + max_body_length];
+ std::size_t body_length_;
+};
+
+#endif // CHAT_MESSAGE_HPP
diff --git a/src/boost/libs/asio/example/cpp11/chat/chat_server.cpp b/src/boost/libs/asio/example/cpp11/chat/chat_server.cpp
new file mode 100644
index 000000000..a96af8628
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/chat/chat_server.cpp
@@ -0,0 +1,227 @@
+//
+// chat_server.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <deque>
+#include <iostream>
+#include <list>
+#include <memory>
+#include <set>
+#include <utility>
+#include <boost/asio.hpp>
+#include "chat_message.hpp"
+
+using boost::asio::ip::tcp;
+
+//----------------------------------------------------------------------
+
+typedef std::deque<chat_message> chat_message_queue;
+
+//----------------------------------------------------------------------
+
+class chat_participant
+{
+public:
+ virtual ~chat_participant() {}
+ virtual void deliver(const chat_message& msg) = 0;
+};
+
+typedef std::shared_ptr<chat_participant> chat_participant_ptr;
+
+//----------------------------------------------------------------------
+
+class chat_room
+{
+public:
+ void join(chat_participant_ptr participant)
+ {
+ participants_.insert(participant);
+ for (auto msg: recent_msgs_)
+ participant->deliver(msg);
+ }
+
+ void leave(chat_participant_ptr participant)
+ {
+ participants_.erase(participant);
+ }
+
+ void deliver(const chat_message& msg)
+ {
+ recent_msgs_.push_back(msg);
+ while (recent_msgs_.size() > max_recent_msgs)
+ recent_msgs_.pop_front();
+
+ for (auto participant: participants_)
+ participant->deliver(msg);
+ }
+
+private:
+ std::set<chat_participant_ptr> participants_;
+ enum { max_recent_msgs = 100 };
+ chat_message_queue recent_msgs_;
+};
+
+//----------------------------------------------------------------------
+
+class chat_session
+ : public chat_participant,
+ public std::enable_shared_from_this<chat_session>
+{
+public:
+ chat_session(tcp::socket socket, chat_room& room)
+ : socket_(std::move(socket)),
+ room_(room)
+ {
+ }
+
+ void start()
+ {
+ room_.join(shared_from_this());
+ do_read_header();
+ }
+
+ void deliver(const chat_message& msg)
+ {
+ bool write_in_progress = !write_msgs_.empty();
+ write_msgs_.push_back(msg);
+ if (!write_in_progress)
+ {
+ do_write();
+ }
+ }
+
+private:
+ void do_read_header()
+ {
+ auto self(shared_from_this());
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ [this, self](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec && read_msg_.decode_header())
+ {
+ do_read_body();
+ }
+ else
+ {
+ room_.leave(shared_from_this());
+ }
+ });
+ }
+
+ void do_read_body()
+ {
+ auto self(shared_from_this());
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
+ [this, self](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ {
+ room_.deliver(read_msg_);
+ do_read_header();
+ }
+ else
+ {
+ room_.leave(shared_from_this());
+ }
+ });
+ }
+
+ void do_write()
+ {
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msgs_.front().data(),
+ write_msgs_.front().length()),
+ [this, self](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ {
+ write_msgs_.pop_front();
+ if (!write_msgs_.empty())
+ {
+ do_write();
+ }
+ }
+ else
+ {
+ room_.leave(shared_from_this());
+ }
+ });
+ }
+
+ tcp::socket socket_;
+ chat_room& room_;
+ chat_message read_msg_;
+ chat_message_queue write_msgs_;
+};
+
+//----------------------------------------------------------------------
+
+class chat_server
+{
+public:
+ chat_server(boost::asio::io_context& io_context,
+ const tcp::endpoint& endpoint)
+ : acceptor_(io_context, endpoint)
+ {
+ do_accept();
+ }
+
+private:
+ void do_accept()
+ {
+ acceptor_.async_accept(
+ [this](boost::system::error_code ec, tcp::socket socket)
+ {
+ if (!ec)
+ {
+ std::make_shared<chat_session>(std::move(socket), room_)->start();
+ }
+
+ do_accept();
+ });
+ }
+
+ tcp::acceptor acceptor_;
+ chat_room room_;
+};
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc < 2)
+ {
+ std::cerr << "Usage: chat_server <port> [<port> ...]\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ std::list<chat_server> servers;
+ for (int i = 1; i < argc; ++i)
+ {
+ tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[i]));
+ servers.emplace_back(io_context, endpoint);
+ }
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/echo/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/echo/Jamfile.v2
new file mode 100644
index 000000000..8af5f5beb
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/echo/Jamfile.v2
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe async_tcp_echo_server : async_tcp_echo_server.cpp ;
+exe async_udp_echo_server : async_udp_echo_server.cpp ;
+exe blocking_tcp_echo_client : blocking_tcp_echo_client.cpp ;
+exe blocking_tcp_echo_server : blocking_tcp_echo_server.cpp ;
+exe blocking_udp_echo_client : blocking_udp_echo_client.cpp ;
+exe blocking_udp_echo_server : blocking_udp_echo_server.cpp ;
diff --git a/src/boost/libs/asio/example/cpp11/echo/async_tcp_echo_server.cpp b/src/boost/libs/asio/example/cpp11/echo/async_tcp_echo_server.cpp
new file mode 100644
index 000000000..f0c674e18
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/echo/async_tcp_echo_server.cpp
@@ -0,0 +1,114 @@
+//
+// async_tcp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <memory>
+#include <utility>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+class session
+ : public std::enable_shared_from_this<session>
+{
+public:
+ session(tcp::socket socket)
+ : socket_(std::move(socket))
+ {
+ }
+
+ void start()
+ {
+ do_read();
+ }
+
+private:
+ void do_read()
+ {
+ auto self(shared_from_this());
+ socket_.async_read_some(boost::asio::buffer(data_, max_length),
+ [this, self](boost::system::error_code ec, std::size_t length)
+ {
+ if (!ec)
+ {
+ do_write(length);
+ }
+ });
+ }
+
+ void do_write(std::size_t length)
+ {
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
+ [this, self](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ {
+ do_read();
+ }
+ });
+ }
+
+ tcp::socket socket_;
+ enum { max_length = 1024 };
+ char data_[max_length];
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
+ {
+ do_accept();
+ }
+
+private:
+ void do_accept()
+ {
+ acceptor_.async_accept(
+ [this](boost::system::error_code ec, tcp::socket socket)
+ {
+ if (!ec)
+ {
+ std::make_shared<session>(std::move(socket))->start();
+ }
+
+ do_accept();
+ });
+ }
+
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: async_tcp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ server s(io_context, std::atoi(argv[1]));
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/echo/async_udp_echo_server.cpp b/src/boost/libs/asio/example/cpp11/echo/async_udp_echo_server.cpp
new file mode 100644
index 000000000..ce3a59990
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/echo/async_udp_echo_server.cpp
@@ -0,0 +1,82 @@
+//
+// async_udp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::udp;
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : socket_(io_context, udp::endpoint(udp::v4(), port))
+ {
+ do_receive();
+ }
+
+ void do_receive()
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(data_, max_length), sender_endpoint_,
+ [this](boost::system::error_code ec, std::size_t bytes_recvd)
+ {
+ if (!ec && bytes_recvd > 0)
+ {
+ do_send(bytes_recvd);
+ }
+ else
+ {
+ do_receive();
+ }
+ });
+ }
+
+ void do_send(std::size_t length)
+ {
+ socket_.async_send_to(
+ boost::asio::buffer(data_, length), sender_endpoint_,
+ [this](boost::system::error_code /*ec*/, std::size_t /*bytes_sent*/)
+ {
+ do_receive();
+ });
+ }
+
+private:
+ udp::socket socket_;
+ udp::endpoint sender_endpoint_;
+ enum { max_length = 1024 };
+ char data_[max_length];
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: async_udp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ server s(io_context, std::atoi(argv[1]));
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/echo/blocking_tcp_echo_client.cpp b/src/boost/libs/asio/example/cpp11/echo/blocking_tcp_echo_client.cpp
new file mode 100644
index 000000000..8e73811b7
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/echo/blocking_tcp_echo_client.cpp
@@ -0,0 +1,55 @@
+//
+// blocking_tcp_echo_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+enum { max_length = 1024 };
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ tcp::socket s(io_context);
+ tcp::resolver resolver(io_context);
+ boost::asio::connect(s, resolver.resolve(argv[1], argv[2]));
+
+ std::cout << "Enter message: ";
+ char request[max_length];
+ std::cin.getline(request, max_length);
+ size_t request_length = std::strlen(request);
+ boost::asio::write(s, boost::asio::buffer(request, request_length));
+
+ char reply[max_length];
+ size_t reply_length = boost::asio::read(s,
+ boost::asio::buffer(reply, request_length));
+ std::cout << "Reply is: ";
+ std::cout.write(reply, reply_length);
+ std::cout << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/echo/blocking_tcp_echo_server.cpp b/src/boost/libs/asio/example/cpp11/echo/blocking_tcp_echo_server.cpp
new file mode 100644
index 000000000..588b4a0c7
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/echo/blocking_tcp_echo_server.cpp
@@ -0,0 +1,74 @@
+//
+// blocking_tcp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <thread>
+#include <utility>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+const int max_length = 1024;
+
+void session(tcp::socket sock)
+{
+ try
+ {
+ for (;;)
+ {
+ char data[max_length];
+
+ boost::system::error_code error;
+ size_t length = sock.read_some(boost::asio::buffer(data), error);
+ if (error == boost::asio::error::eof)
+ break; // Connection closed cleanly by peer.
+ else if (error)
+ throw boost::system::system_error(error); // Some other error.
+
+ boost::asio::write(sock, boost::asio::buffer(data, length));
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception in thread: " << e.what() << "\n";
+ }
+}
+
+void server(boost::asio::io_context& io_context, unsigned short port)
+{
+ tcp::acceptor a(io_context, tcp::endpoint(tcp::v4(), port));
+ for (;;)
+ {
+ std::thread(session, a.accept()).detach();
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: blocking_tcp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ server(io_context, std::atoi(argv[1]));
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/echo/blocking_udp_echo_client.cpp b/src/boost/libs/asio/example/cpp11/echo/blocking_udp_echo_client.cpp
new file mode 100644
index 000000000..8ed9e3a29
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/echo/blocking_udp_echo_client.cpp
@@ -0,0 +1,58 @@
+//
+// blocking_udp_echo_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::udp;
+
+enum { max_length = 1024 };
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: blocking_udp_echo_client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ udp::socket s(io_context, udp::endpoint(udp::v4(), 0));
+
+ udp::resolver resolver(io_context);
+ udp::resolver::results_type endpoints =
+ resolver.resolve(udp::v4(), argv[1], argv[2]);
+
+ std::cout << "Enter message: ";
+ char request[max_length];
+ std::cin.getline(request, max_length);
+ size_t request_length = std::strlen(request);
+ s.send_to(boost::asio::buffer(request, request_length), *endpoints.begin());
+
+ char reply[max_length];
+ udp::endpoint sender_endpoint;
+ size_t reply_length = s.receive_from(
+ boost::asio::buffer(reply, max_length), sender_endpoint);
+ std::cout << "Reply is: ";
+ std::cout.write(reply, reply_length);
+ std::cout << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/echo/blocking_udp_echo_server.cpp b/src/boost/libs/asio/example/cpp11/echo/blocking_udp_echo_server.cpp
new file mode 100644
index 000000000..e1f41e28f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/echo/blocking_udp_echo_server.cpp
@@ -0,0 +1,52 @@
+//
+// blocking_udp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::udp;
+
+enum { max_length = 1024 };
+
+void server(boost::asio::io_context& io_context, unsigned short port)
+{
+ udp::socket sock(io_context, udp::endpoint(udp::v4(), port));
+ for (;;)
+ {
+ char data[max_length];
+ udp::endpoint sender_endpoint;
+ size_t length = sock.receive_from(
+ boost::asio::buffer(data, max_length), sender_endpoint);
+ sock.send_to(boost::asio::buffer(data, length), sender_endpoint);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: blocking_udp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ server(io_context, std::atoi(argv[1]));
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/executors/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/executors/Jamfile.v2
new file mode 100644
index 000000000..26ef1fda1
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/executors/Jamfile.v2
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe actor : actor.cpp ;
+exe bank_account_1 : bank_account_1.cpp ;
+exe bank_account_2 : bank_account_2.cpp ;
+exe fork_join : fork_join.cpp ;
+exe pipeline : pipeline.cpp ;
+exe priority_scheduler : priority_scheduler.cpp ;
diff --git a/src/boost/libs/asio/example/cpp11/executors/actor.cpp b/src/boost/libs/asio/example/cpp11/executors/actor.cpp
new file mode 100644
index 000000000..2e3311d40
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/executors/actor.cpp
@@ -0,0 +1,286 @@
+#include <boost/asio/defer.hpp>
+#include <boost/asio/executor.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/system_executor.hpp>
+#include <condition_variable>
+#include <deque>
+#include <memory>
+#include <mutex>
+#include <typeinfo>
+#include <vector>
+
+using boost::asio::defer;
+using boost::asio::executor;
+using boost::asio::post;
+using boost::asio::strand;
+using boost::asio::system_executor;
+
+//------------------------------------------------------------------------------
+// A tiny actor framework
+// ~~~~~~~~~~~~~~~~~~~~~~
+
+class actor;
+
+// Used to identify the sender and recipient of messages.
+typedef actor* actor_address;
+
+// Base class for all registered message handlers.
+class message_handler_base
+{
+public:
+ virtual ~message_handler_base() {}
+
+ // Used to determine which message handlers receive an incoming message.
+ virtual const std::type_info& message_id() const = 0;
+};
+
+// Base class for a handler for a specific message type.
+template <class Message>
+class message_handler : public message_handler_base
+{
+public:
+ // Handle an incoming message.
+ virtual void handle_message(Message msg, actor_address from) = 0;
+};
+
+// Concrete message handler for a specific message type.
+template <class Actor, class Message>
+class mf_message_handler : public message_handler<Message>
+{
+public:
+ // Construct a message handler to invoke the specified member function.
+ mf_message_handler(void (Actor::* mf)(Message, actor_address), Actor* a)
+ : function_(mf), actor_(a)
+ {
+ }
+
+ // Used to determine which message handlers receive an incoming message.
+ virtual const std::type_info& message_id() const
+ {
+ return typeid(Message);
+ }
+
+ // Handle an incoming message.
+ virtual void handle_message(Message msg, actor_address from)
+ {
+ (actor_->*function_)(std::move(msg), from);
+ }
+
+ // Determine whether the message handler represents the specified function.
+ bool is_function(void (Actor::* mf)(Message, actor_address)) const
+ {
+ return mf == function_;
+ }
+
+private:
+ void (Actor::* function_)(Message, actor_address);
+ Actor* actor_;
+};
+
+// Base class for all actors.
+class actor
+{
+public:
+ virtual ~actor()
+ {
+ }
+
+ // Obtain the actor's address for use as a message sender or recipient.
+ actor_address address()
+ {
+ return this;
+ }
+
+ // Send a message from one actor to another.
+ template <class Message>
+ friend void send(Message msg, actor_address from, actor_address to)
+ {
+ // Execute the message handler in the context of the target's executor.
+ post(to->executor_,
+ [=]
+ {
+ to->call_handler(std::move(msg), from);
+ });
+ }
+
+protected:
+ // Construct the actor to use the specified executor for all message handlers.
+ actor(executor e)
+ : executor_(std::move(e))
+ {
+ }
+
+ // Register a handler for a specific message type. Duplicates are permitted.
+ template <class Actor, class Message>
+ void register_handler(void (Actor::* mf)(Message, actor_address))
+ {
+ handlers_.push_back(
+ std::make_shared<mf_message_handler<Actor, Message>>(
+ mf, static_cast<Actor*>(this)));
+ }
+
+ // Deregister a handler. Removes only the first matching handler.
+ template <class Actor, class Message>
+ void deregister_handler(void (Actor::* mf)(Message, actor_address))
+ {
+ const std::type_info& id = typeid(message_handler<Message>);
+ for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter)
+ {
+ if ((*iter)->message_id() == id)
+ {
+ auto mh = static_cast<mf_message_handler<Actor, Message>*>(iter->get());
+ if (mh->is_function(mf))
+ {
+ handlers_.erase(iter);
+ return;
+ }
+ }
+ }
+ }
+
+ // Send a message from within a message handler.
+ template <class Message>
+ void tail_send(Message msg, actor_address to)
+ {
+ // Execute the message handler in the context of the target's executor.
+ actor* from = this;
+ defer(to->executor_,
+ [=]
+ {
+ to->call_handler(std::move(msg), from);
+ });
+ }
+
+private:
+ // Find the matching message handlers, if any, and call them.
+ template <class Message>
+ void call_handler(Message msg, actor_address from)
+ {
+ const std::type_info& message_id = typeid(Message);
+ for (auto& h: handlers_)
+ {
+ if (h->message_id() == message_id)
+ {
+ auto mh = static_cast<message_handler<Message>*>(h.get());
+ mh->handle_message(msg, from);
+ }
+ }
+ }
+
+ // All messages associated with a single actor object should be processed
+ // non-concurrently. We use a strand to ensure non-concurrent execution even
+ // if the underlying executor may use multiple threads.
+ strand<executor> executor_;
+
+ std::vector<std::shared_ptr<message_handler_base>> handlers_;
+};
+
+// A concrete actor that allows synchronous message retrieval.
+template <class Message>
+class receiver : public actor
+{
+public:
+ receiver()
+ : actor(system_executor())
+ {
+ register_handler(&receiver::message_handler);
+ }
+
+ // Block until a message has been received.
+ Message wait()
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ condition_.wait(lock, [this]{ return !message_queue_.empty(); });
+ Message msg(std::move(message_queue_.front()));
+ message_queue_.pop_front();
+ return msg;
+ }
+
+private:
+ // Handle a new message by adding it to the queue and waking a waiter.
+ void message_handler(Message msg, actor_address /* from */)
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ message_queue_.push_back(std::move(msg));
+ condition_.notify_one();
+ }
+
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::deque<Message> message_queue_;
+};
+
+//------------------------------------------------------------------------------
+
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+
+using boost::asio::thread_pool;
+
+class member : public actor
+{
+public:
+ explicit member(executor e)
+ : actor(std::move(e))
+ {
+ register_handler(&member::init_handler);
+ }
+
+private:
+ void init_handler(actor_address next, actor_address from)
+ {
+ next_ = next;
+ caller_ = from;
+
+ register_handler(&member::token_handler);
+ deregister_handler(&member::init_handler);
+ }
+
+ void token_handler(int token, actor_address /*from*/)
+ {
+ int msg(token);
+ actor_address to(caller_);
+
+ if (token > 0)
+ {
+ msg = token - 1;
+ to = next_;
+ }
+
+ tail_send(msg, to);
+ }
+
+ actor_address next_;
+ actor_address caller_;
+};
+
+int main()
+{
+ const std::size_t num_threads = 16;
+ const int num_hops = 50000000;
+ const std::size_t num_actors = 503;
+ const int token_value = (num_hops + num_actors - 1) / num_actors;
+ const std::size_t actors_per_thread = num_actors / num_threads;
+
+ struct single_thread_pool : thread_pool { single_thread_pool() : thread_pool(1) {} };
+ single_thread_pool pools[num_threads];
+ std::vector<std::shared_ptr<member>> members(num_actors);
+ receiver<int> rcvr;
+
+ // Create the member actors.
+ for (std::size_t i = 0; i < num_actors; ++i)
+ members[i] = std::make_shared<member>(pools[(i / actors_per_thread) % num_threads].get_executor());
+
+ // Initialise the actors by passing each one the address of the next actor in the ring.
+ for (std::size_t i = num_actors, next_i = 0; i > 0; next_i = --i)
+ send(members[next_i]->address(), rcvr.address(), members[i - 1]->address());
+
+ // Send exactly one token to each actor, all with the same initial value, rounding up if required.
+ for (std::size_t i = 0; i < num_actors; ++i)
+ send(token_value, rcvr.address(), members[i]->address());
+
+ // Wait for all signal messages, indicating the tokens have all reached zero.
+ for (std::size_t i = 0; i < num_actors; ++i)
+ rcvr.wait();
+}
diff --git a/src/boost/libs/asio/example/cpp11/executors/bank_account_1.cpp b/src/boost/libs/asio/example/cpp11/executors/bank_account_1.cpp
new file mode 100644
index 000000000..35b659be8
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/executors/bank_account_1.cpp
@@ -0,0 +1,54 @@
+#include <boost/asio/post.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+
+using boost::asio::post;
+using boost::asio::thread_pool;
+
+// Traditional active object pattern.
+// Member functions do not block.
+
+class bank_account
+{
+ int balance_ = 0;
+ mutable thread_pool pool_{1};
+
+public:
+ void deposit(int amount)
+ {
+ post(pool_, [=]
+ {
+ balance_ += amount;
+ });
+ }
+
+ void withdraw(int amount)
+ {
+ post(pool_, [=]
+ {
+ if (balance_ >= amount)
+ balance_ -= amount;
+ });
+ }
+
+ void print_balance() const
+ {
+ post(pool_, [=]
+ {
+ std::cout << "balance = " << balance_ << "\n";
+ });
+ }
+
+ ~bank_account()
+ {
+ pool_.join();
+ }
+};
+
+int main()
+{
+ bank_account acct;
+ acct.deposit(20);
+ acct.withdraw(10);
+ acct.print_balance();
+}
diff --git a/src/boost/libs/asio/example/cpp11/executors/bank_account_2.cpp b/src/boost/libs/asio/example/cpp11/executors/bank_account_2.cpp
new file mode 100644
index 000000000..aebff7645
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/executors/bank_account_2.cpp
@@ -0,0 +1,54 @@
+#include <boost/asio/post.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <boost/asio/use_future.hpp>
+#include <iostream>
+
+using boost::asio::post;
+using boost::asio::thread_pool;
+using boost::asio::use_future;
+
+// Traditional active object pattern.
+// Member functions block until operation is finished.
+
+class bank_account
+{
+ int balance_ = 0;
+ mutable thread_pool pool_{1};
+
+public:
+ void deposit(int amount)
+ {
+ post(pool_,
+ use_future([=]
+ {
+ balance_ += amount;
+ })).get();
+ }
+
+ void withdraw(int amount)
+ {
+ post(pool_,
+ use_future([=]
+ {
+ if (balance_ >= amount)
+ balance_ -= amount;
+ })).get();
+ }
+
+ int balance() const
+ {
+ return post(pool_,
+ use_future([=]
+ {
+ return balance_;
+ })).get();
+ }
+};
+
+int main()
+{
+ bank_account acct;
+ acct.deposit(20);
+ acct.withdraw(10);
+ std::cout << "balance = " << acct.balance() << "\n";
+}
diff --git a/src/boost/libs/asio/example/cpp11/executors/fork_join.cpp b/src/boost/libs/asio/example/cpp11/executors/fork_join.cpp
new file mode 100644
index 000000000..98926d53f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/executors/fork_join.cpp
@@ -0,0 +1,328 @@
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <numeric>
+
+using boost::asio::dispatch;
+using boost::asio::execution_context;
+using boost::asio::thread_pool;
+
+// A fixed-size thread pool used to implement fork/join semantics. Functions
+// are scheduled using a simple FIFO queue. Implementing work stealing, or
+// using a queue based on atomic operations, are left as tasks for the reader.
+class fork_join_pool : public execution_context
+{
+public:
+ // The constructor starts a thread pool with the specified number of threads.
+ // Note that the thread_count is not a fixed limit on the pool's concurrency.
+ // Additional threads may temporarily be added to the pool if they join a
+ // fork_executor.
+ explicit fork_join_pool(
+ std::size_t thread_count = std::thread::hardware_concurrency() * 2)
+ : use_count_(1),
+ threads_(thread_count)
+ {
+ try
+ {
+ // Ask each thread in the pool to dequeue and execute functions until
+ // it is time to shut down, i.e. the use count is zero.
+ for (thread_count_ = 0; thread_count_ < thread_count; ++thread_count_)
+ {
+ dispatch(threads_, [&]
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ while (use_count_ > 0)
+ if (!execute_next(lock))
+ condition_.wait(lock);
+ });
+ }
+ }
+ catch (...)
+ {
+ stop_threads();
+ threads_.join();
+ throw;
+ }
+ }
+
+ // The destructor waits for the pool to finish executing functions.
+ ~fork_join_pool()
+ {
+ stop_threads();
+ threads_.join();
+ }
+
+private:
+ friend class fork_executor;
+
+ // The base for all functions that are queued in the pool.
+ struct function_base
+ {
+ std::shared_ptr<std::size_t> work_count_;
+ void (*execute_)(std::shared_ptr<function_base>& p);
+ };
+
+ // Execute the next function from the queue, if any. Returns true if a
+ // function was executed, and false if the queue was empty.
+ bool execute_next(std::unique_lock<std::mutex>& lock)
+ {
+ if (queue_.empty())
+ return false;
+ auto p(queue_.front());
+ queue_.pop();
+ lock.unlock();
+ execute(lock, p);
+ return true;
+ }
+
+ // Execute a function and decrement the outstanding work.
+ void execute(std::unique_lock<std::mutex>& lock,
+ std::shared_ptr<function_base>& p)
+ {
+ std::shared_ptr<std::size_t> work_count(std::move(p->work_count_));
+ try
+ {
+ p->execute_(p);
+ lock.lock();
+ do_work_finished(work_count);
+ }
+ catch (...)
+ {
+ lock.lock();
+ do_work_finished(work_count);
+ throw;
+ }
+ }
+
+ // Increment outstanding work.
+ void do_work_started(const std::shared_ptr<std::size_t>& work_count) noexcept
+ {
+ if (++(*work_count) == 1)
+ ++use_count_;
+ }
+
+ // Decrement outstanding work. Notify waiting threads if we run out.
+ void do_work_finished(const std::shared_ptr<std::size_t>& work_count) noexcept
+ {
+ if (--(*work_count) == 0)
+ {
+ --use_count_;
+ condition_.notify_all();
+ }
+ }
+
+ // Dispatch a function, executing it immediately if the queue is already
+ // loaded. Otherwise adds the function to the queue and wakes a thread.
+ void do_dispatch(std::shared_ptr<function_base> p,
+ const std::shared_ptr<std::size_t>& work_count)
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (queue_.size() > thread_count_ * 16)
+ {
+ do_work_started(work_count);
+ lock.unlock();
+ execute(lock, p);
+ }
+ else
+ {
+ queue_.push(p);
+ do_work_started(work_count);
+ condition_.notify_one();
+ }
+ }
+
+ // Add a function to the queue and wake a thread.
+ void do_post(std::shared_ptr<function_base> p,
+ const std::shared_ptr<std::size_t>& work_count)
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ queue_.push(p);
+ do_work_started(work_count);
+ condition_.notify_one();
+ }
+
+ // Ask all threads to shut down.
+ void stop_threads()
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ --use_count_;
+ condition_.notify_all();
+ }
+
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::queue<std::shared_ptr<function_base>> queue_;
+ std::size_t use_count_;
+ std::size_t thread_count_;
+ thread_pool threads_;
+};
+
+// A class that satisfies the Executor requirements. Every function or piece of
+// work associated with a fork_executor is part of a single, joinable group.
+class fork_executor
+{
+public:
+ fork_executor(fork_join_pool& ctx)
+ : context_(ctx),
+ work_count_(std::make_shared<std::size_t>(0))
+ {
+ }
+
+ fork_join_pool& context() const noexcept
+ {
+ return context_;
+ }
+
+ void on_work_started() const noexcept
+ {
+ std::lock_guard<std::mutex> lock(context_.mutex_);
+ context_.do_work_started(work_count_);
+ }
+
+ void on_work_finished() const noexcept
+ {
+ std::lock_guard<std::mutex> lock(context_.mutex_);
+ context_.do_work_finished(work_count_);
+ }
+
+ template <class Func, class Alloc>
+ void dispatch(Func&& f, const Alloc& a) const
+ {
+ auto p(std::allocate_shared<function<Func>>(
+ typename std::allocator_traits<Alloc>::template rebind_alloc<char>(a),
+ std::move(f), work_count_));
+ context_.do_dispatch(p, work_count_);
+ }
+
+ template <class Func, class Alloc>
+ void post(Func f, const Alloc& a) const
+ {
+ auto p(std::allocate_shared<function<Func>>(
+ typename std::allocator_traits<Alloc>::template rebind_alloc<char>(a),
+ std::move(f), work_count_));
+ context_.do_post(p, work_count_);
+ }
+
+ template <class Func, class Alloc>
+ void defer(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ friend bool operator==(const fork_executor& a,
+ const fork_executor& b) noexcept
+ {
+ return a.work_count_ == b.work_count_;
+ }
+
+ friend bool operator!=(const fork_executor& a,
+ const fork_executor& b) noexcept
+ {
+ return a.work_count_ != b.work_count_;
+ }
+
+ // Block until all work associated with the executor is complete. While it is
+ // waiting, the thread may be borrowed to execute functions from the queue.
+ void join() const
+ {
+ std::unique_lock<std::mutex> lock(context_.mutex_);
+ while (*work_count_ > 0)
+ if (!context_.execute_next(lock))
+ context_.condition_.wait(lock);
+ }
+
+private:
+ template <class Func>
+ struct function : fork_join_pool::function_base
+ {
+ explicit function(Func f, const std::shared_ptr<std::size_t>& w)
+ : function_(std::move(f))
+ {
+ work_count_ = w;
+ execute_ = [](std::shared_ptr<fork_join_pool::function_base>& p)
+ {
+ Func tmp(std::move(static_cast<function*>(p.get())->function_));
+ p.reset();
+ tmp();
+ };
+ }
+
+ Func function_;
+ };
+
+ fork_join_pool& context_;
+ std::shared_ptr<std::size_t> work_count_;
+};
+
+// Helper class to automatically join a fork_executor when exiting a scope.
+class join_guard
+{
+public:
+ explicit join_guard(const fork_executor& ex) : ex_(ex) {}
+ join_guard(const join_guard&) = delete;
+ join_guard(join_guard&&) = delete;
+ ~join_guard() { ex_.join(); }
+
+private:
+ fork_executor ex_;
+};
+
+//------------------------------------------------------------------------------
+
+#include <algorithm>
+#include <iostream>
+#include <random>
+#include <vector>
+
+fork_join_pool pool;
+
+template <class Iterator>
+void fork_join_sort(Iterator begin, Iterator end)
+{
+ std::size_t n = end - begin;
+ if (n > 32768)
+ {
+ {
+ fork_executor fork(pool);
+ join_guard join(fork);
+ dispatch(fork, [=]{ fork_join_sort(begin, begin + n / 2); });
+ dispatch(fork, [=]{ fork_join_sort(begin + n / 2, end); });
+ }
+ std::inplace_merge(begin, begin + n / 2, end);
+ }
+ else
+ {
+ std::sort(begin, end);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ std::cerr << "Usage: fork_join <size>\n";
+ return 1;
+ }
+
+ std::vector<double> vec(std::atoll(argv[1]));
+ std::iota(vec.begin(), vec.end(), 0);
+
+ std::random_device rd;
+ std::mt19937 g(rd());
+ std::shuffle(vec.begin(), vec.end(), g);
+
+ std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
+
+ fork_join_sort(vec.begin(), vec.end());
+
+ std::chrono::steady_clock::duration elapsed = std::chrono::steady_clock::now() - start;
+
+ std::cout << "sort took ";
+ std::cout << std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
+ std::cout << " microseconds" << std::endl;
+}
diff --git a/src/boost/libs/asio/example/cpp11/executors/pipeline.cpp b/src/boost/libs/asio/example/cpp11/executors/pipeline.cpp
new file mode 100644
index 000000000..9c2a778fe
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/executors/pipeline.cpp
@@ -0,0 +1,299 @@
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/system_executor.hpp>
+#include <boost/asio/use_future.hpp>
+#include <condition_variable>
+#include <future>
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <vector>
+#include <cctype>
+
+using boost::asio::execution_context;
+using boost::asio::executor_binder;
+using boost::asio::get_associated_executor;
+using boost::asio::post;
+using boost::asio::system_executor;
+using boost::asio::use_future;
+using boost::asio::use_service;
+
+// An executor that launches a new thread for each function submitted to it.
+// This class satisfies the Executor requirements.
+class thread_executor
+{
+private:
+ // Service to track all threads started through a thread_executor.
+ class thread_bag : public execution_context::service
+ {
+ public:
+ typedef thread_bag key_type;
+
+ explicit thread_bag(execution_context& ctx)
+ : execution_context::service(ctx)
+ {
+ }
+
+ void add_thread(std::thread&& t)
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ threads_.push_back(std::move(t));
+ }
+
+ private:
+ virtual void shutdown()
+ {
+ for (auto& t : threads_)
+ t.join();
+ }
+
+ std::mutex mutex_;
+ std::vector<std::thread> threads_;
+ };
+
+public:
+ execution_context& context() const noexcept
+ {
+ return system_executor().context();
+ }
+
+ void on_work_started() const noexcept
+ {
+ // This executor doesn't count work.
+ }
+
+ void on_work_finished() const noexcept
+ {
+ // This executor doesn't count work.
+ }
+
+ template <class Func, class Alloc>
+ void dispatch(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ template <class Func, class Alloc>
+ void post(Func f, const Alloc&) const
+ {
+ thread_bag& bag = use_service<thread_bag>(context());
+ bag.add_thread(std::thread(std::move(f)));
+ }
+
+ template <class Func, class Alloc>
+ void defer(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ friend bool operator==(const thread_executor&,
+ const thread_executor&) noexcept
+ {
+ return true;
+ }
+
+ friend bool operator!=(const thread_executor&,
+ const thread_executor&) noexcept
+ {
+ return false;
+ }
+};
+
+// Base class for all thread-safe queue implementations.
+class queue_impl_base
+{
+ template <class> friend class queue_front;
+ template <class> friend class queue_back;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ bool stop_ = false;
+};
+
+// Underlying implementation of a thread-safe queue, shared between the
+// queue_front and queue_back classes.
+template <class T>
+class queue_impl : public queue_impl_base
+{
+ template <class> friend class queue_front;
+ template <class> friend class queue_back;
+ std::queue<T> queue_;
+};
+
+// The front end of a queue between consecutive pipeline stages.
+template <class T>
+class queue_front
+{
+public:
+ typedef T value_type;
+
+ explicit queue_front(std::shared_ptr<queue_impl<T>> impl)
+ : impl_(impl)
+ {
+ }
+
+ void push(T t)
+ {
+ std::unique_lock<std::mutex> lock(impl_->mutex_);
+ impl_->queue_.push(std::move(t));
+ impl_->condition_.notify_one();
+ }
+
+ void stop()
+ {
+ std::unique_lock<std::mutex> lock(impl_->mutex_);
+ impl_->stop_ = true;
+ impl_->condition_.notify_one();
+ }
+
+private:
+ std::shared_ptr<queue_impl<T>> impl_;
+};
+
+// The back end of a queue between consecutive pipeline stages.
+template <class T>
+class queue_back
+{
+public:
+ typedef T value_type;
+
+ explicit queue_back(std::shared_ptr<queue_impl<T>> impl)
+ : impl_(impl)
+ {
+ }
+
+ bool pop(T& t)
+ {
+ std::unique_lock<std::mutex> lock(impl_->mutex_);
+ while (impl_->queue_.empty() && !impl_->stop_)
+ impl_->condition_.wait(lock);
+ if (!impl_->queue_.empty())
+ {
+ t = impl_->queue_.front();
+ impl_->queue_.pop();
+ return true;
+ }
+ return false;
+ }
+
+private:
+ std::shared_ptr<queue_impl<T>> impl_;
+};
+
+// Launch the last stage in a pipeline.
+template <class T, class F>
+std::future<void> pipeline(queue_back<T> in, F f)
+{
+ // Get the function's associated executor, defaulting to thread_executor.
+ auto ex = get_associated_executor(f, thread_executor());
+
+ // Run the function, and as we're the last stage return a future so that the
+ // caller can wait for the pipeline to finish.
+ return post(ex, use_future([in, f]() mutable { f(in); }));
+}
+
+// Launch an intermediate stage in a pipeline.
+template <class T, class F, class... Tail>
+std::future<void> pipeline(queue_back<T> in, F f, Tail... t)
+{
+ // Determine the output queue type.
+ typedef typename executor_binder<F, thread_executor>::second_argument_type::value_type output_value_type;
+
+ // Create the output queue and its implementation.
+ auto out_impl = std::make_shared<queue_impl<output_value_type>>();
+ queue_front<output_value_type> out(out_impl);
+ queue_back<output_value_type> next_in(out_impl);
+
+ // Get the function's associated executor, defaulting to thread_executor.
+ auto ex = get_associated_executor(f, thread_executor());
+
+ // Run the function.
+ post(ex, [in, out, f]() mutable
+ {
+ f(in, out);
+ out.stop();
+ });
+
+ // Launch the rest of the pipeline.
+ return pipeline(next_in, std::move(t)...);
+}
+
+// Launch the first stage in a pipeline.
+template <class F, class... Tail>
+std::future<void> pipeline(F f, Tail... t)
+{
+ // Determine the output queue type.
+ typedef typename executor_binder<F, thread_executor>::argument_type::value_type output_value_type;
+
+ // Create the output queue and its implementation.
+ auto out_impl = std::make_shared<queue_impl<output_value_type>>();
+ queue_front<output_value_type> out(out_impl);
+ queue_back<output_value_type> next_in(out_impl);
+
+ // Get the function's associated executor, defaulting to thread_executor.
+ auto ex = get_associated_executor(f, thread_executor());
+
+ // Run the function.
+ post(ex, [out, f]() mutable
+ {
+ f(out);
+ out.stop();
+ });
+
+ // Launch the rest of the pipeline.
+ return pipeline(next_in, std::move(t)...);
+}
+
+//------------------------------------------------------------------------------
+
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+#include <string>
+
+using boost::asio::bind_executor;
+using boost::asio::thread_pool;
+
+void reader(queue_front<std::string> out)
+{
+ std::string line;
+ while (std::getline(std::cin, line))
+ out.push(line);
+}
+
+void filter(queue_back<std::string> in, queue_front<std::string> out)
+{
+ std::string line;
+ while (in.pop(line))
+ if (line.length() > 5)
+ out.push(line);
+}
+
+void upper(queue_back<std::string> in, queue_front<std::string> out)
+{
+ std::string line;
+ while (in.pop(line))
+ {
+ std::string new_line;
+ for (char c : line)
+ new_line.push_back(std::toupper(c));
+ out.push(new_line);
+ }
+}
+
+void writer(queue_back<std::string> in)
+{
+ std::size_t count = 0;
+ std::string line;
+ while (in.pop(line))
+ std::cout << count++ << ": " << line << std::endl;
+}
+
+int main()
+{
+ thread_pool pool;
+
+ auto f = pipeline(reader, filter, bind_executor(pool, upper), writer);
+ f.wait();
+}
diff --git a/src/boost/libs/asio/example/cpp11/executors/priority_scheduler.cpp b/src/boost/libs/asio/example/cpp11/executors/priority_scheduler.cpp
new file mode 100644
index 000000000..7c9bc80d7
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/executors/priority_scheduler.cpp
@@ -0,0 +1,174 @@
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <condition_variable>
+#include <iostream>
+#include <memory>
+#include <mutex>
+#include <queue>
+
+using boost::asio::dispatch;
+using boost::asio::execution_context;
+
+class priority_scheduler : public execution_context
+{
+public:
+ // A class that satisfies the Executor requirements.
+ class executor_type
+ {
+ public:
+ executor_type(priority_scheduler& ctx, int pri) noexcept
+ : context_(ctx), priority_(pri)
+ {
+ }
+
+ priority_scheduler& context() const noexcept
+ {
+ return context_;
+ }
+
+ void on_work_started() const noexcept
+ {
+ // This executor doesn't count work. Instead, the scheduler simply runs
+ // until explicitly stopped.
+ }
+
+ void on_work_finished() const noexcept
+ {
+ // This executor doesn't count work. Instead, the scheduler simply runs
+ // until explicitly stopped.
+ }
+
+ template <class Func, class Alloc>
+ void dispatch(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ template <class Func, class Alloc>
+ void post(Func f, const Alloc& a) const
+ {
+ auto p(std::allocate_shared<item<Func>>(
+ typename std::allocator_traits<
+ Alloc>::template rebind_alloc<char>(a),
+ priority_, std::move(f)));
+ std::lock_guard<std::mutex> lock(context_.mutex_);
+ context_.queue_.push(p);
+ context_.condition_.notify_one();
+ }
+
+ template <class Func, class Alloc>
+ void defer(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ friend bool operator==(const executor_type& a,
+ const executor_type& b) noexcept
+ {
+ return &a.context_ == &b.context_;
+ }
+
+ friend bool operator!=(const executor_type& a,
+ const executor_type& b) noexcept
+ {
+ return &a.context_ != &b.context_;
+ }
+
+ private:
+ priority_scheduler& context_;
+ int priority_;
+ };
+
+ ~priority_scheduler() noexcept
+ {
+ shutdown();
+ destroy();
+ }
+
+ executor_type get_executor(int pri = 0) noexcept
+ {
+ return executor_type(*const_cast<priority_scheduler*>(this), pri);
+ }
+
+ void run()
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ for (;;)
+ {
+ condition_.wait(lock, [&]{ return stopped_ || !queue_.empty(); });
+ if (stopped_)
+ return;
+ auto p(queue_.top());
+ queue_.pop();
+ lock.unlock();
+ p->execute_(p);
+ lock.lock();
+ }
+ }
+
+ void stop()
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ stopped_ = true;
+ condition_.notify_all();
+ }
+
+private:
+ struct item_base
+ {
+ int priority_;
+ void (*execute_)(std::shared_ptr<item_base>&);
+ };
+
+ template <class Func>
+ struct item : item_base
+ {
+ item(int pri, Func f) : function_(std::move(f))
+ {
+ priority_ = pri;
+ execute_ = [](std::shared_ptr<item_base>& p)
+ {
+ Func tmp(std::move(static_cast<item*>(p.get())->function_));
+ p.reset();
+ tmp();
+ };
+ }
+
+ Func function_;
+ };
+
+ struct item_comp
+ {
+ bool operator()(
+ const std::shared_ptr<item_base>& a,
+ const std::shared_ptr<item_base>& b)
+ {
+ return a->priority_ < b->priority_;
+ }
+ };
+
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::priority_queue<
+ std::shared_ptr<item_base>,
+ std::vector<std::shared_ptr<item_base>>,
+ item_comp> queue_;
+ bool stopped_ = false;
+};
+
+int main()
+{
+ priority_scheduler sched;
+ auto low = sched.get_executor(0);
+ auto med = sched.get_executor(1);
+ auto high = sched.get_executor(2);
+ dispatch(low, []{ std::cout << "1\n"; });
+ dispatch(low, []{ std::cout << "11\n"; });
+ dispatch(med, []{ std::cout << "2\n"; });
+ dispatch(med, []{ std::cout << "22\n"; });
+ dispatch(high, []{ std::cout << "3\n"; });
+ dispatch(high, []{ std::cout << "33\n"; });
+ dispatch(high, []{ std::cout << "333\n"; });
+ dispatch(sched.get_executor(-1), [&]{ sched.stop(); });
+ sched.run();
+}
diff --git a/src/boost/libs/asio/example/cpp11/fork/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/fork/Jamfile.v2
new file mode 100644
index 000000000..d6b8eb264
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/fork/Jamfile.v2
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe daemon
+ : daemon.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe process_per_connection
+ : process_per_connection.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/fork/daemon.cpp b/src/boost/libs/asio/example/cpp11/fork/daemon.cpp
new file mode 100644
index 000000000..76f9571db
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/fork/daemon.cpp
@@ -0,0 +1,189 @@
+//
+// daemon.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <array>
+#include <ctime>
+#include <iostream>
+#include <syslog.h>
+#include <unistd.h>
+
+using boost::asio::ip::udp;
+
+class udp_daytime_server
+{
+public:
+ udp_daytime_server(boost::asio::io_context& io_context)
+ : socket_(io_context, {udp::v4(), 13})
+ {
+ receive();
+ }
+
+private:
+ void receive()
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(recv_buffer_), remote_endpoint_,
+ [this](boost::system::error_code ec, std::size_t /*n*/)
+ {
+ if (!ec)
+ {
+ using namespace std; // For time_t, time and ctime;
+ time_t now = time(0);
+ std::string message = ctime(&now);
+
+ boost::system::error_code ignored_ec;
+ socket_.send_to(boost::asio::buffer(message),
+ remote_endpoint_, 0, ignored_ec);
+ }
+
+ receive();
+ });
+ }
+
+ udp::socket socket_;
+ udp::endpoint remote_endpoint_;
+ std::array<char, 1> recv_buffer_;
+};
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context;
+
+ // Initialise the server before becoming a daemon. If the process is
+ // started from a shell, this means any errors will be reported back to the
+ // user.
+ udp_daytime_server server(io_context);
+
+ // Register signal handlers so that the daemon may be shut down. You may
+ // also want to register for other signals, such as SIGHUP to trigger a
+ // re-read of a configuration file.
+ boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
+ signals.async_wait(
+ [&](boost::system::error_code /*ec*/, int /*signo*/)
+ {
+ io_context.stop();
+ });
+
+ // Inform the io_context that we are about to become a daemon. The
+ // io_context cleans up any internal resources, such as threads, that may
+ // interfere with forking.
+ io_context.notify_fork(boost::asio::io_context::fork_prepare);
+
+ // Fork the process and have the parent exit. If the process was started
+ // from a shell, this returns control to the user. Forking a new process is
+ // also a prerequisite for the subsequent call to setsid().
+ if (pid_t pid = fork())
+ {
+ if (pid > 0)
+ {
+ // We're in the parent process and need to exit.
+ //
+ // When the exit() function is used, the program terminates without
+ // invoking local variables' destructors. Only global variables are
+ // destroyed. As the io_context object is a local variable, this means
+ // we do not have to call:
+ //
+ // io_context.notify_fork(boost::asio::io_context::fork_parent);
+ //
+ // However, this line should be added before each call to exit() if
+ // using a global io_context object. An additional call:
+ //
+ // io_context.notify_fork(boost::asio::io_context::fork_prepare);
+ //
+ // should also precede the second fork().
+ exit(0);
+ }
+ else
+ {
+ syslog(LOG_ERR | LOG_USER, "First fork failed: %m");
+ return 1;
+ }
+ }
+
+ // Make the process a new session leader. This detaches it from the
+ // terminal.
+ setsid();
+
+ // A process inherits its working directory from its parent. This could be
+ // on a mounted filesystem, which means that the running daemon would
+ // prevent this filesystem from being unmounted. Changing to the root
+ // directory avoids this problem.
+ chdir("/");
+
+ // The file mode creation mask is also inherited from the parent process.
+ // We don't want to restrict the permissions on files created by the
+ // daemon, so the mask is cleared.
+ umask(0);
+
+ // A second fork ensures the process cannot acquire a controlling terminal.
+ if (pid_t pid = fork())
+ {
+ if (pid > 0)
+ {
+ exit(0);
+ }
+ else
+ {
+ syslog(LOG_ERR | LOG_USER, "Second fork failed: %m");
+ return 1;
+ }
+ }
+
+ // Close the standard streams. This decouples the daemon from the terminal
+ // that started it.
+ close(0);
+ close(1);
+ close(2);
+
+ // We don't want the daemon to have any standard input.
+ if (open("/dev/null", O_RDONLY) < 0)
+ {
+ syslog(LOG_ERR | LOG_USER, "Unable to open /dev/null: %m");
+ return 1;
+ }
+
+ // Send standard output to a log file.
+ const char* output = "/tmp/asio.daemon.out";
+ const int flags = O_WRONLY | O_CREAT | O_APPEND;
+ const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ if (open(output, flags, mode) < 0)
+ {
+ syslog(LOG_ERR | LOG_USER, "Unable to open output file %s: %m", output);
+ return 1;
+ }
+
+ // Also send standard error to the same log file.
+ if (dup(1) < 0)
+ {
+ syslog(LOG_ERR | LOG_USER, "Unable to dup output descriptor: %m");
+ return 1;
+ }
+
+ // Inform the io_context that we have finished becoming a daemon. The
+ // io_context uses this opportunity to create any internal file descriptors
+ // that need to be private to the new process.
+ io_context.notify_fork(boost::asio::io_context::fork_child);
+
+ // The io_context can now be used normally.
+ syslog(LOG_INFO | LOG_USER, "Daemon started");
+ io_context.run();
+ syslog(LOG_INFO | LOG_USER, "Daemon stopped");
+ }
+ catch (std::exception& e)
+ {
+ syslog(LOG_ERR | LOG_USER, "Exception: %s", e.what());
+ std::cerr << "Exception: " << e.what() << std::endl;
+ }
+}
diff --git a/src/boost/libs/asio/example/cpp11/fork/process_per_connection.cpp b/src/boost/libs/asio/example/cpp11/fork/process_per_connection.cpp
new file mode 100644
index 000000000..4fb4ae889
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/fork/process_per_connection.cpp
@@ -0,0 +1,162 @@
+//
+// process_per_connection.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+using boost::asio::ip::tcp;
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, unsigned short port)
+ : io_context_(io_context),
+ signal_(io_context, SIGCHLD),
+ acceptor_(io_context, {tcp::v4(), port}),
+ socket_(io_context)
+ {
+ wait_for_signal();
+ accept();
+ }
+
+private:
+ void wait_for_signal()
+ {
+ signal_.async_wait(
+ [this](boost::system::error_code /*ec*/, int /*signo*/)
+ {
+ // Only the parent process should check for this signal. We can
+ // determine whether we are in the parent by checking if the acceptor
+ // is still open.
+ if (acceptor_.is_open())
+ {
+ // Reap completed child processes so that we don't end up with
+ // zombies.
+ int status = 0;
+ while (waitpid(-1, &status, WNOHANG) > 0) {}
+
+ wait_for_signal();
+ }
+ });
+ }
+
+ void accept()
+ {
+ acceptor_.async_accept(
+ [this](boost::system::error_code ec, tcp::socket new_socket)
+ {
+ if (!ec)
+ {
+ // Take ownership of the newly accepted socket.
+ socket_ = std::move(new_socket);
+
+ // Inform the io_context that we are about to fork. The io_context
+ // cleans up any internal resources, such as threads, that may
+ // interfere with forking.
+ io_context_.notify_fork(boost::asio::io_context::fork_prepare);
+
+ if (fork() == 0)
+ {
+ // Inform the io_context that the fork is finished and that this
+ // is the child process. The io_context uses this opportunity to
+ // create any internal file descriptors that must be private to
+ // the new process.
+ io_context_.notify_fork(boost::asio::io_context::fork_child);
+
+ // The child won't be accepting new connections, so we can close
+ // the acceptor. It remains open in the parent.
+ acceptor_.close();
+
+ // The child process is not interested in processing the SIGCHLD
+ // signal.
+ signal_.cancel();
+
+ read();
+ }
+ else
+ {
+
+ // Inform the io_context that the fork is finished (or failed)
+ // and that this is the parent process. The io_context uses this
+ // opportunity to recreate any internal resources that were
+ // cleaned up during preparation for the fork.
+ io_context_.notify_fork(boost::asio::io_context::fork_parent);
+
+ // The parent process can now close the newly accepted socket. It
+ // remains open in the child.
+ socket_.close();
+
+ accept();
+ }
+ }
+ else
+ {
+ std::cerr << "Accept error: " << ec.message() << std::endl;
+ accept();
+ }
+ });
+ }
+
+ void read()
+ {
+ socket_.async_read_some(boost::asio::buffer(data_),
+ [this](boost::system::error_code ec, std::size_t length)
+ {
+ if (!ec)
+ write(length);
+ });
+ }
+
+ void write(std::size_t length)
+ {
+ boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
+ [this](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ read();
+ });
+ }
+
+ boost::asio::io_context& io_context_;
+ boost::asio::signal_set signal_;
+ tcp::acceptor acceptor_;
+ tcp::socket socket_;
+ std::array<char, 1024> data_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: process_per_connection <port>\n";
+ return 1;
+ }
+
+ boost::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;
+ }
+}
diff --git a/src/boost/libs/asio/example/cpp11/futures/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/futures/Jamfile.v2
new file mode 100644
index 000000000..59c8a374b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/futures/Jamfile.v2
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : daytime_client.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/futures/daytime_client.cpp b/src/boost/libs/asio/example/cpp11/futures/daytime_client.cpp
new file mode 100644
index 000000000..7f787ed0a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/futures/daytime_client.cpp
@@ -0,0 +1,94 @@
+//
+// daytime_client.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <future>
+#include <iostream>
+#include <thread>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/use_future.hpp>
+
+using boost::asio::ip::udp;
+
+void get_daytime(boost::asio::io_context& io_context, const char* hostname)
+{
+ try
+ {
+ udp::resolver resolver(io_context);
+
+ std::future<udp::resolver::results_type> endpoints =
+ resolver.async_resolve(
+ udp::v4(), hostname, "daytime",
+ boost::asio::use_future);
+
+ // The async_resolve operation above returns the endpoints as a future
+ // value that is not retrieved ...
+
+ udp::socket socket(io_context, udp::v4());
+
+ std::array<char, 1> send_buf = {{ 0 }};
+ std::future<std::size_t> send_length =
+ socket.async_send_to(boost::asio::buffer(send_buf),
+ *endpoints.get().begin(), // ... until here. This call may block.
+ boost::asio::use_future);
+
+ // Do other things here while the send completes.
+
+ send_length.get(); // Blocks until the send is complete. Throws any errors.
+
+ std::array<char, 128> recv_buf;
+ udp::endpoint sender_endpoint;
+ std::future<std::size_t> recv_length =
+ socket.async_receive_from(
+ boost::asio::buffer(recv_buf),
+ sender_endpoint,
+ boost::asio::use_future);
+
+ // Do other things here while the receive completes.
+
+ std::cout.write(
+ recv_buf.data(),
+ recv_length.get()); // Blocks until receive is complete.
+ }
+ catch (std::system_error& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: daytime_client <host>" << std::endl;
+ return 1;
+ }
+
+ // We run the io_context off in its own thread so that it operates
+ // completely asynchronously with respect to the rest of the program.
+ boost::asio::io_context io_context;
+ auto work = boost::asio::make_work_guard(io_context);
+ std::thread thread([&io_context](){ io_context.run(); });
+
+ get_daytime(io_context, argv[1]);
+
+ io_context.stop();
+ thread.join();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/handler_tracking/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/handler_tracking/Jamfile.v2
new file mode 100644
index 000000000..20eb3aae1
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/handler_tracking/Jamfile.v2
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe async_tcp_echo_server
+ : async_tcp_echo_server.cpp
+ /boost/system//boost_system
+ : <include>.
+ <define>BOOST_ALL_NO_LIB=1
+ <define>BOOST_ASIO_CUSTOM_HANDLER_TRACKING=\\\"custom_tracking.hpp\\\"
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp b/src/boost/libs/asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp
new file mode 100644
index 000000000..f0c674e18
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp
@@ -0,0 +1,114 @@
+//
+// async_tcp_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <iostream>
+#include <memory>
+#include <utility>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+class session
+ : public std::enable_shared_from_this<session>
+{
+public:
+ session(tcp::socket socket)
+ : socket_(std::move(socket))
+ {
+ }
+
+ void start()
+ {
+ do_read();
+ }
+
+private:
+ void do_read()
+ {
+ auto self(shared_from_this());
+ socket_.async_read_some(boost::asio::buffer(data_, max_length),
+ [this, self](boost::system::error_code ec, std::size_t length)
+ {
+ if (!ec)
+ {
+ do_write(length);
+ }
+ });
+ }
+
+ void do_write(std::size_t length)
+ {
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
+ [this, self](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ {
+ do_read();
+ }
+ });
+ }
+
+ tcp::socket socket_;
+ enum { max_length = 1024 };
+ char data_[max_length];
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, short port)
+ : acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
+ {
+ do_accept();
+ }
+
+private:
+ void do_accept()
+ {
+ acceptor_.async_accept(
+ [this](boost::system::error_code ec, tcp::socket socket)
+ {
+ if (!ec)
+ {
+ std::make_shared<session>(std::move(socket))->start();
+ }
+
+ do_accept();
+ });
+ }
+
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: async_tcp_echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ server s(io_context, std::atoi(argv[1]));
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/handler_tracking/custom_tracking.hpp b/src/boost/libs/asio/example/cpp11/handler_tracking/custom_tracking.hpp
new file mode 100644
index 000000000..1bb5b6ad9
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/handler_tracking/custom_tracking.hpp
@@ -0,0 +1,201 @@
+//
+// custom_tracking.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 CUSTOM_TRACKING_HPP
+#define CUSTOM_TRACKING_HPP
+
+#include <cinttypes>
+#include <cstdint>
+#include <cstdio>
+
+# define BOOST_ASIO_INHERIT_TRACKED_HANDLER \
+ : public ::custom_tracking::tracked_handler
+
+# define BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER \
+ , public ::custom_tracking::tracked_handler
+
+# define BOOST_ASIO_HANDLER_TRACKING_INIT \
+ ::custom_tracking::init()
+
+# define BOOST_ASIO_HANDLER_CREATION(args) \
+ ::custom_tracking::creation args
+
+# define BOOST_ASIO_HANDLER_COMPLETION(args) \
+ ::custom_tracking::completion tracked_completion args
+
+# define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) \
+ tracked_completion.invocation_begin args
+
+# define BOOST_ASIO_HANDLER_INVOCATION_END \
+ tracked_completion.invocation_end()
+
+# define BOOST_ASIO_HANDLER_OPERATION(args) \
+ ::custom_tracking::operation args
+
+# define BOOST_ASIO_HANDLER_REACTOR_REGISTRATION(args) \
+ ::custom_tracking::reactor_registration args
+
+# define BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args) \
+ ::custom_tracking::reactor_deregistration args
+
+# define BOOST_ASIO_HANDLER_REACTOR_READ_EVENT 1
+# define BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT 2
+# define BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT 4
+
+# define BOOST_ASIO_HANDLER_REACTOR_EVENTS(args) \
+ ::custom_tracking::reactor_events args
+
+# define BOOST_ASIO_HANDLER_REACTOR_OPERATION(args) \
+ ::custom_tracking::reactor_operation args
+
+struct custom_tracking
+{
+ // Base class for objects containing tracked handlers.
+ struct tracked_handler
+ {
+ std::uintmax_t handler_id_ = 0; // To uniquely identify a handler.
+ std::uintmax_t tree_id_ = 0; // To identify related handlers.
+ const char* object_type_; // The object type associated with the handler.
+ std::uintmax_t native_handle_; // Native handle, if any.
+ };
+
+ // Initialise the tracking system.
+ static void init()
+ {
+ }
+
+ // Record the creation of a tracked handler.
+ static void creation(boost::asio::execution_context& /*ctx*/,
+ tracked_handler& h, const char* object_type, void* /*object*/,
+ std::uintmax_t native_handle, const char* op_name)
+ {
+ // Generate a unique id for the new handler.
+ static std::atomic<std::uintmax_t> next_handler_id{1};
+ h.handler_id_ = next_handler_id++;
+
+ // Copy the tree identifier forward from the current handler.
+ if (*current_completion())
+ h.tree_id_ = (*current_completion())->handler_.tree_id_;
+
+ // Store various attributes of the operation to use in later output.
+ h.object_type_ = object_type;
+ h.native_handle_ = native_handle;
+
+ std::printf(
+ "Starting operation %s.%s for native_handle = %" PRIuMAX
+ ", handler = %" PRIuMAX ", tree = %" PRIuMAX "\n",
+ object_type, op_name, h.native_handle_, h.handler_id_, h.tree_id_);
+ }
+
+ struct completion
+ {
+ explicit completion(const tracked_handler& h)
+ : handler_(h),
+ next_(*current_completion())
+ {
+ *current_completion() = this;
+ }
+
+ completion(const completion&) = delete;
+ completion& operator=(const completion&) = delete;
+
+ // Destructor records only when an exception is thrown from the handler, or
+ // if the memory is being freed without the handler having been invoked.
+ ~completion()
+ {
+ *current_completion() = next_;
+ }
+
+ // Records that handler is to be invoked with the specified arguments.
+ template <class... Args>
+ void invocation_begin(Args&&... /*args*/)
+ {
+ std::printf("Entering handler %" PRIuMAX " in tree %" PRIuMAX "\n",
+ handler_.handler_id_, handler_.tree_id_);
+ }
+
+ // Record that handler invocation has ended.
+ void invocation_end()
+ {
+ std::printf("Leaving handler %" PRIuMAX " in tree %" PRIuMAX "\n",
+ handler_.handler_id_, handler_.tree_id_);
+ }
+
+ tracked_handler handler_;
+
+ // Completions may nest. Here we stash a pointer to the outer completion.
+ completion* next_;
+ };
+
+ static completion** current_completion()
+ {
+ static BOOST_ASIO_THREAD_KEYWORD completion* current = nullptr;
+ return &current;
+ }
+
+ // Record an operation that is not directly associated with a handler.
+ static void operation(boost::asio::execution_context& /*ctx*/,
+ const char* /*object_type*/, void* /*object*/,
+ std::uintmax_t /*native_handle*/, const char* /*op_name*/)
+ {
+ }
+
+ // Record that a descriptor has been registered with the reactor.
+ static void reactor_registration(boost::asio::execution_context& context,
+ uintmax_t native_handle, uintmax_t registration)
+ {
+ std::printf("Adding to reactor native_handle = %" PRIuMAX
+ ", registration = %" PRIuMAX "\n", native_handle, registration);
+ }
+
+ // Record that a descriptor has been deregistered from the reactor.
+ static void reactor_deregistration(boost::asio::execution_context& context,
+ uintmax_t native_handle, uintmax_t registration)
+ {
+ std::printf("Removing from reactor native_handle = %" PRIuMAX
+ ", registration = %" PRIuMAX "\n", native_handle, registration);
+ }
+
+ // Record reactor-based readiness events associated with a descriptor.
+ static void reactor_events(boost::asio::execution_context& context,
+ uintmax_t registration, unsigned events)
+ {
+ std::printf(
+ "Reactor readiness for registration = %" PRIuMAX ", events =%s%s%s\n",
+ registration,
+ (events & BOOST_ASIO_HANDLER_REACTOR_READ_EVENT) ? " read" : "",
+ (events & BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT) ? " write" : "",
+ (events & BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT) ? " error" : "");
+ }
+
+ // Record a reactor-based operation that is associated with a handler.
+ static void reactor_operation(const tracked_handler& h,
+ const char* op_name, const boost::system::error_code& ec)
+ {
+ std::printf(
+ "Performed operation %s.%s for native_handle = %" PRIuMAX
+ ", ec = %s:%d\n", h.object_type_, op_name, h.native_handle_,
+ ec.category().name(), ec.value());
+ }
+
+ // Record a reactor-based operation that is associated with a handler.
+ static void reactor_operation(const tracked_handler& h,
+ const char* op_name, const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ std::printf(
+ "Performed operation %s.%s for native_handle = %" PRIuMAX
+ ", ec = %s:%d, n = %" PRIuMAX "\n", h.object_type_, op_name,
+ h.native_handle_, ec.category().name(), ec.value(),
+ static_cast<uintmax_t>(bytes_transferred));
+ }
+};
+
+#endif // CUSTOM_TRACKING_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/http/server/Jamfile.v2
new file mode 100644
index 000000000..084b7b472
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/Jamfile.v2
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : connection.cpp
+ connection_manager.cpp
+ main.cpp
+ mime_types.cpp
+ reply.cpp
+ request_handler.cpp
+ request_parser.cpp
+ server.cpp
+ /boost/system//boost_system
+ /boost/thread//boost_thread
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/http/server/connection.cpp b/src/boost/libs/asio/example/cpp11/http/server/connection.cpp
new file mode 100644
index 000000000..cdf31cc24
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/connection.cpp
@@ -0,0 +1,94 @@
+//
+// connection.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <vector>
+#include "connection_manager.hpp"
+#include "request_handler.hpp"
+
+namespace http {
+namespace server {
+
+connection::connection(boost::asio::ip::tcp::socket socket,
+ connection_manager& manager, request_handler& handler)
+ : socket_(std::move(socket)),
+ connection_manager_(manager),
+ request_handler_(handler)
+{
+}
+
+void connection::start()
+{
+ do_read();
+}
+
+void connection::stop()
+{
+ socket_.close();
+}
+
+void connection::do_read()
+{
+ auto self(shared_from_this());
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ [this, self](boost::system::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();
+ }
+ }
+ else if (ec != boost::asio::error::operation_aborted)
+ {
+ connection_manager_.stop(shared_from_this());
+ }
+ });
+}
+
+void connection::do_write()
+{
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_, reply_.to_buffers(),
+ [this, self](boost::system::error_code ec, std::size_t)
+ {
+ if (!ec)
+ {
+ // Initiate graceful connection closure.
+ boost::system::error_code ignored_ec;
+ socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both,
+ ignored_ec);
+ }
+
+ if (ec != boost::asio::error::operation_aborted)
+ {
+ connection_manager_.stop(shared_from_this());
+ }
+ });
+}
+
+} // namespace server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp11/http/server/connection.hpp b/src/boost/libs/asio/example/cpp11/http/server/connection.hpp
new file mode 100644
index 000000000..83fcc0408
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/connection.hpp
@@ -0,0 +1,79 @@
+//
+// connection.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_CONNECTION_HPP
+#define HTTP_CONNECTION_HPP
+
+#include <array>
+#include <memory>
+#include <boost/asio.hpp>
+#include "reply.hpp"
+#include "request.hpp"
+#include "request_handler.hpp"
+#include "request_parser.hpp"
+
+namespace http {
+namespace server {
+
+class connection_manager;
+
+/// 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(boost::asio::ip::tcp::socket socket,
+ connection_manager& manager, request_handler& handler);
+
+ /// Start the first asynchronous operation for the connection.
+ void start();
+
+ /// Stop all asynchronous operations associated with the connection.
+ void stop();
+
+private:
+ /// Perform an asynchronous read operation.
+ void do_read();
+
+ /// Perform an asynchronous write operation.
+ void do_write();
+
+ /// Socket for the connection.
+ boost::asio::ip::tcp::socket socket_;
+
+ /// The manager for this connection.
+ connection_manager& connection_manager_;
+
+ /// 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 server
+} // namespace http
+
+#endif // HTTP_CONNECTION_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/connection_manager.cpp b/src/boost/libs/asio/example/cpp11/http/server/connection_manager.cpp
new file mode 100644
index 000000000..c07642189
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/connection_manager.cpp
@@ -0,0 +1,40 @@
+//
+// connection_manager.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_manager.hpp"
+
+namespace http {
+namespace server {
+
+connection_manager::connection_manager()
+{
+}
+
+void connection_manager::start(connection_ptr c)
+{
+ connections_.insert(c);
+ c->start();
+}
+
+void connection_manager::stop(connection_ptr c)
+{
+ connections_.erase(c);
+ c->stop();
+}
+
+void connection_manager::stop_all()
+{
+ for (auto c: connections_)
+ c->stop();
+ connections_.clear();
+}
+
+} // namespace server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp11/http/server/connection_manager.hpp b/src/boost/libs/asio/example/cpp11/http/server/connection_manager.hpp
new file mode 100644
index 000000000..aac32c6f0
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/connection_manager.hpp
@@ -0,0 +1,48 @@
+//
+// connection_manager.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_CONNECTION_MANAGER_HPP
+#define HTTP_CONNECTION_MANAGER_HPP
+
+#include <set>
+#include "connection.hpp"
+
+namespace http {
+namespace server {
+
+/// Manages open connections so that they may be cleanly stopped when the server
+/// needs to shut down.
+class connection_manager
+{
+public:
+ connection_manager(const connection_manager&) = delete;
+ connection_manager& operator=(const connection_manager&) = delete;
+
+ /// Construct a connection manager.
+ connection_manager();
+
+ /// Add the specified connection to the manager and start it.
+ void start(connection_ptr c);
+
+ /// Stop the specified connection.
+ void stop(connection_ptr c);
+
+ /// Stop all connections.
+ void stop_all();
+
+private:
+ /// The managed connections.
+ std::set<connection_ptr> connections_;
+};
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_CONNECTION_MANAGER_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/header.hpp b/src/boost/libs/asio/example/cpp11/http/server/header.hpp
new file mode 100644
index 000000000..7e176c3b0
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/header.hpp
@@ -0,0 +1,28 @@
+//
+// header.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_HEADER_HPP
+#define HTTP_HEADER_HPP
+
+#include <string>
+
+namespace http {
+namespace server {
+
+struct header
+{
+ std::string name;
+ std::string value;
+};
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_HEADER_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/main.cpp b/src/boost/libs/asio/example/cpp11/http/server/main.cpp
new file mode 100644
index 000000000..8236fa6b7
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/main.cpp
@@ -0,0 +1,43 @@
+//
+// main.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include "server.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;
+ }
+
+ // Initialise the server.
+ http::server::server s(argv[1], argv[2], argv[3]);
+
+ // Run the server until stopped.
+ s.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/http/server/mime_types.cpp b/src/boost/libs/asio/example/cpp11/http/server/mime_types.cpp
new file mode 100644
index 000000000..806c58f9d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/mime_types.cpp
@@ -0,0 +1,45 @@
+//
+// mime_types.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 server {
+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" }
+};
+
+std::string extension_to_type(const std::string& extension)
+{
+ for (mapping m: mappings)
+ {
+ if (m.extension == extension)
+ {
+ return m.mime_type;
+ }
+ }
+
+ return "text/plain";
+}
+
+} // namespace mime_types
+} // namespace server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp11/http/server/mime_types.hpp b/src/boost/libs/asio/example/cpp11/http/server/mime_types.hpp
new file mode 100644
index 000000000..e9bb88268
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/mime_types.hpp
@@ -0,0 +1,27 @@
+//
+// mime_types.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_MIME_TYPES_HPP
+#define HTTP_MIME_TYPES_HPP
+
+#include <string>
+
+namespace http {
+namespace server {
+namespace mime_types {
+
+/// Convert a file extension into a MIME type.
+std::string extension_to_type(const std::string& extension);
+
+} // namespace mime_types
+} // namespace server
+} // namespace http
+
+#endif // HTTP_MIME_TYPES_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/reply.cpp b/src/boost/libs/asio/example/cpp11/http/server/reply.cpp
new file mode 100644
index 000000000..1ff869f2d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/reply.cpp
@@ -0,0 +1,255 @@
+//
+// reply.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 server {
+
+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";
+
+boost::asio::const_buffer to_buffer(reply::status_type status)
+{
+ switch (status)
+ {
+ case reply::ok:
+ return boost::asio::buffer(ok);
+ case reply::created:
+ return boost::asio::buffer(created);
+ case reply::accepted:
+ return boost::asio::buffer(accepted);
+ case reply::no_content:
+ return boost::asio::buffer(no_content);
+ case reply::multiple_choices:
+ return boost::asio::buffer(multiple_choices);
+ case reply::moved_permanently:
+ return boost::asio::buffer(moved_permanently);
+ case reply::moved_temporarily:
+ return boost::asio::buffer(moved_temporarily);
+ case reply::not_modified:
+ return boost::asio::buffer(not_modified);
+ case reply::bad_request:
+ return boost::asio::buffer(bad_request);
+ case reply::unauthorized:
+ return boost::asio::buffer(unauthorized);
+ case reply::forbidden:
+ return boost::asio::buffer(forbidden);
+ case reply::not_found:
+ return boost::asio::buffer(not_found);
+ case reply::internal_server_error:
+ return boost::asio::buffer(internal_server_error);
+ case reply::not_implemented:
+ return boost::asio::buffer(not_implemented);
+ case reply::bad_gateway:
+ return boost::asio::buffer(bad_gateway);
+ case reply::service_unavailable:
+ return boost::asio::buffer(service_unavailable);
+ default:
+ return boost::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<boost::asio::const_buffer> reply::to_buffers()
+{
+ std::vector<boost::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(boost::asio::buffer(h.name));
+ buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator));
+ buffers.push_back(boost::asio::buffer(h.value));
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ }
+ buffers.push_back(boost::asio::buffer(misc_strings::crlf));
+ buffers.push_back(boost::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 server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp11/http/server/reply.hpp b/src/boost/libs/asio/example/cpp11/http/server/reply.hpp
new file mode 100644
index 000000000..6a3240e2d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/reply.hpp
@@ -0,0 +1,64 @@
+//
+// reply.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_REPLY_HPP
+#define HTTP_REPLY_HPP
+
+#include <string>
+#include <vector>
+#include <boost/asio.hpp>
+#include "header.hpp"
+
+namespace http {
+namespace server {
+
+/// 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<boost::asio::const_buffer> to_buffers();
+
+ /// Get a stock reply.
+ static reply stock_reply(status_type status);
+};
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_REPLY_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/request.hpp b/src/boost/libs/asio/example/cpp11/http/server/request.hpp
new file mode 100644
index 000000000..358133512
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/request.hpp
@@ -0,0 +1,34 @@
+//
+// request.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_REQUEST_HPP
+#define HTTP_REQUEST_HPP
+
+#include <string>
+#include <vector>
+#include "header.hpp"
+
+namespace http {
+namespace server {
+
+/// 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 server
+} // namespace http
+
+#endif // HTTP_REQUEST_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/request_handler.cpp b/src/boost/libs/asio/example/cpp11/http/server/request_handler.cpp
new file mode 100644
index 000000000..c0ee6139c
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/request_handler.cpp
@@ -0,0 +1,121 @@
+//
+// request_handler.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 server {
+
+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 server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp11/http/server/request_handler.hpp b/src/boost/libs/asio/example/cpp11/http/server/request_handler.hpp
new file mode 100644
index 000000000..b1670c468
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/request_handler.hpp
@@ -0,0 +1,47 @@
+//
+// request_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_REQUEST_HANDLER_HPP
+#define HTTP_REQUEST_HANDLER_HPP
+
+#include <string>
+
+namespace http {
+namespace server {
+
+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 server
+} // namespace http
+
+#endif // HTTP_REQUEST_HANDLER_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/request_parser.cpp b/src/boost/libs/asio/example/cpp11/http/server/request_parser.cpp
new file mode 100644
index 000000000..27a253201
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/request_parser.cpp
@@ -0,0 +1,315 @@
+//
+// request_parser.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 server {
+
+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 server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp11/http/server/request_parser.hpp b/src/boost/libs/asio/example/cpp11/http/server/request_parser.hpp
new file mode 100644
index 000000000..131b468de
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/request_parser.hpp
@@ -0,0 +1,96 @@
+//
+// request_parser.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_REQUEST_PARSER_HPP
+#define HTTP_REQUEST_PARSER_HPP
+
+#include <tuple>
+
+namespace http {
+namespace server {
+
+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 server
+} // namespace http
+
+#endif // HTTP_REQUEST_PARSER_HPP
diff --git a/src/boost/libs/asio/example/cpp11/http/server/server.cpp b/src/boost/libs/asio/example/cpp11/http/server/server.cpp
new file mode 100644
index 000000000..3e5ca4e1f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/server.cpp
@@ -0,0 +1,94 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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>
+
+namespace http {
+namespace server {
+
+server::server(const std::string& address, const std::string& port,
+ const std::string& doc_root)
+ : io_context_(1),
+ signals_(io_context_),
+ acceptor_(io_context_),
+ connection_manager_(),
+ 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).
+ boost::asio::ip::tcp::resolver resolver(io_context_);
+ boost::asio::ip::tcp::endpoint endpoint =
+ *resolver.resolve(address, port).begin();
+ acceptor_.open(endpoint.protocol());
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor_.bind(endpoint);
+ acceptor_.listen();
+
+ do_accept();
+}
+
+void server::run()
+{
+ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the server is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+ io_context_.run();
+}
+
+void server::do_accept()
+{
+ acceptor_.async_accept(
+ [this](boost::system::error_code ec, boost::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)
+ {
+ connection_manager_.start(std::make_shared<connection>(
+ std::move(socket), connection_manager_, request_handler_));
+ }
+
+ do_accept();
+ });
+}
+
+void server::do_await_stop()
+{
+ signals_.async_wait(
+ [this](boost::system::error_code /*ec*/, int /*signo*/)
+ {
+ // The server is stopped by cancelling all outstanding asynchronous
+ // operations. Once all operations have finished the io_context::run()
+ // call will exit.
+ acceptor_.close();
+ connection_manager_.stop_all();
+ });
+}
+
+} // namespace server
+} // namespace http
diff --git a/src/boost/libs/asio/example/cpp11/http/server/server.hpp b/src/boost/libs/asio/example/cpp11/http/server/server.hpp
new file mode 100644
index 000000000..9d72a340f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/http/server/server.hpp
@@ -0,0 +1,64 @@
+//
+// server.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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_SERVER_HPP
+#define HTTP_SERVER_HPP
+
+#include <boost/asio.hpp>
+#include <string>
+#include "connection.hpp"
+#include "connection_manager.hpp"
+#include "request_handler.hpp"
+
+namespace http {
+namespace server {
+
+/// 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);
+
+ /// 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 io_context used to perform asynchronous operations.
+ boost::asio::io_context io_context_;
+
+ /// The signal_set is used to register for process termination notifications.
+ boost::asio::signal_set signals_;
+
+ /// Acceptor used to listen for incoming connections.
+ boost::asio::ip::tcp::acceptor acceptor_;
+
+ /// The connection manager which owns all live connections.
+ connection_manager connection_manager_;
+
+ /// The handler for all incoming requests.
+ request_handler request_handler_;
+};
+
+} // namespace server
+} // namespace http
+
+#endif // HTTP_SERVER_HPP
diff --git a/src/boost/libs/asio/example/cpp11/invocation/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/invocation/Jamfile.v2
new file mode 100644
index 000000000..d348adce7
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/invocation/Jamfile.v2
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe prioritised_handlers
+ : prioritised_handlers.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/invocation/prioritised_handlers.cpp b/src/boost/libs/asio/example/cpp11/invocation/prioritised_handlers.cpp
new file mode 100644
index 000000000..9bf9c26a3
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/invocation/prioritised_handlers.cpp
@@ -0,0 +1,202 @@
+//
+// prioritised_handlers.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <iostream>
+#include <memory>
+#include <queue>
+
+using boost::asio::ip::tcp;
+
+class handler_priority_queue : public boost::asio::execution_context
+{
+public:
+ template <typename Function>
+ void add(int priority, Function function)
+ {
+ std::unique_ptr<queued_handler_base> handler(
+ new queued_handler<Function>(
+ priority, std::move(function)));
+
+ handlers_.push(std::move(handler));
+ }
+
+ void execute_all()
+ {
+ while (!handlers_.empty())
+ {
+ handlers_.top()->execute();
+ handlers_.pop();
+ }
+ }
+
+ class executor
+ {
+ public:
+ executor(handler_priority_queue& q, int p)
+ : context_(q), priority_(p)
+ {
+ }
+
+ handler_priority_queue& context() const noexcept
+ {
+ return context_;
+ }
+
+ template <typename Function, typename Allocator>
+ void dispatch(Function f, const Allocator&) const
+ {
+ context_.add(priority_, std::move(f));
+ }
+
+ template <typename Function, typename Allocator>
+ void post(Function f, const Allocator&) const
+ {
+ context_.add(priority_, std::move(f));
+ }
+
+ template <typename Function, typename Allocator>
+ void defer(Function f, const Allocator&) const
+ {
+ context_.add(priority_, std::move(f));
+ }
+
+ void on_work_started() const noexcept {}
+ void on_work_finished() const noexcept {}
+
+ bool operator==(const executor& other) const noexcept
+ {
+ return &context_ == &other.context_ && priority_ == other.priority_;
+ }
+
+ bool operator!=(const executor& other) const noexcept
+ {
+ return !operator==(other);
+ }
+
+ private:
+ handler_priority_queue& context_;
+ int priority_;
+ };
+
+ template <typename Handler>
+ boost::asio::executor_binder<Handler, executor>
+ wrap(int priority, Handler handler)
+ {
+ return boost::asio::bind_executor(
+ executor(*this, priority), std::move(handler));
+ }
+
+private:
+ class queued_handler_base
+ {
+ public:
+ queued_handler_base(int p)
+ : priority_(p)
+ {
+ }
+
+ virtual ~queued_handler_base()
+ {
+ }
+
+ virtual void execute() = 0;
+
+ friend bool operator<(const std::unique_ptr<queued_handler_base>& a,
+ const std::unique_ptr<queued_handler_base>& b) noexcept
+ {
+ return a->priority_ < b->priority_;
+ }
+
+ private:
+ int priority_;
+ };
+
+ template <typename Function>
+ class queued_handler : public queued_handler_base
+ {
+ public:
+ queued_handler(int p, Function f)
+ : queued_handler_base(p), function_(std::move(f))
+ {
+ }
+
+ void execute() override
+ {
+ function_();
+ }
+
+ private:
+ Function function_;
+ };
+
+ std::priority_queue<std::unique_ptr<queued_handler_base>> handlers_;
+};
+
+//----------------------------------------------------------------------
+
+void high_priority_handler(const boost::system::error_code& /*ec*/,
+ tcp::socket /*socket*/)
+{
+ std::cout << "High priority handler\n";
+}
+
+void middle_priority_handler(const boost::system::error_code& /*ec*/)
+{
+ std::cout << "Middle priority handler\n";
+}
+
+struct low_priority_handler
+{
+ // Make the handler a move-only type.
+ low_priority_handler() = default;
+ low_priority_handler(const low_priority_handler&) = delete;
+ low_priority_handler(low_priority_handler&&) = default;
+
+ void operator()()
+ {
+ std::cout << "Low priority handler\n";
+ }
+};
+
+int main()
+{
+ boost::asio::io_context io_context;
+
+ handler_priority_queue pri_queue;
+
+ // Post a completion handler to be run immediately.
+ boost::asio::post(io_context, pri_queue.wrap(0, low_priority_handler()));
+
+ // Start an asynchronous accept that will complete immediately.
+ tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 0);
+ tcp::acceptor acceptor(io_context, endpoint);
+ tcp::socket server_socket(io_context);
+ acceptor.async_accept(pri_queue.wrap(100, high_priority_handler));
+ tcp::socket client_socket(io_context);
+ client_socket.connect(acceptor.local_endpoint());
+
+ // Set a deadline timer to expire immediately.
+ boost::asio::steady_timer timer(io_context);
+ timer.expires_at(boost::asio::steady_timer::clock_type::time_point::min());
+ timer.async_wait(pri_queue.wrap(42, middle_priority_handler));
+
+ while (io_context.run_one())
+ {
+ // The custom invocation hook adds the handlers to the priority queue
+ // rather than executing them from within the poll_one() call.
+ while (io_context.poll_one())
+ ;
+
+ pri_queue.execute_all();
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/iostreams/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/iostreams/Jamfile.v2
new file mode 100644
index 000000000..a201dfd80
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/iostreams/Jamfile.v2
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe http_client : http_client.cpp ;
diff --git a/src/boost/libs/asio/example/cpp11/iostreams/http_client.cpp b/src/boost/libs/asio/example/cpp11/iostreams/http_client.cpp
new file mode 100644
index 000000000..97d5f728c
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/iostreams/http_client.cpp
@@ -0,0 +1,91 @@
+//
+// http_client.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/ip/tcp.hpp>
+
+using boost::asio::ip::tcp;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cout << "Usage: http_client <server> <path>\n";
+ std::cout << "Example:\n";
+ std::cout << " http_client www.boost.org /LICENSE_1_0.txt\n";
+ return 1;
+ }
+
+ boost::asio::ip::tcp::iostream s;
+
+ // The entire sequence of I/O operations must complete within 60 seconds.
+ // If an expiry occurs, the socket is automatically closed and the stream
+ // becomes bad.
+ s.expires_after(std::chrono::seconds(60));
+
+ // Establish a connection to the server.
+ s.connect(argv[1], "http");
+ if (!s)
+ {
+ std::cout << "Unable to connect: " << s.error().message() << "\n";
+ return 1;
+ }
+
+ // Send 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.
+ s << "GET " << argv[2] << " HTTP/1.0\r\n";
+ s << "Host: " << argv[1] << "\r\n";
+ s << "Accept: */*\r\n";
+ s << "Connection: close\r\n\r\n";
+
+ // By default, the stream is tied with itself. This means that the stream
+ // automatically flush the buffered output before attempting a read. It is
+ // not necessary not explicitly flush the stream at this point.
+
+ // Check that response is OK.
+ std::string http_version;
+ s >> http_version;
+ unsigned int status_code;
+ s >> status_code;
+ std::string status_message;
+ std::getline(s, status_message);
+ if (!s || 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;
+ }
+
+ // Process the response headers, which are terminated by a blank line.
+ std::string header;
+ while (std::getline(s, header) && header != "\r")
+ std::cout << header << "\n";
+ std::cout << "\n";
+
+ // Write the remaining data to output.
+ std::cout << s.rdbuf();
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/local/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/local/Jamfile.v2
new file mode 100644
index 000000000..e231001fa
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/local/Jamfile.v2
@@ -0,0 +1,78 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe connect_pair
+ : connect_pair.cpp
+ /boost/system//boost_system
+ /boost/thread//boost_thread
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe iostream_client
+ : iostream_client.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe stream_client
+ : stream_client.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe stream_server
+ : stream_server.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/local/connect_pair.cpp b/src/boost/libs/asio/example/cpp11/local/connect_pair.cpp
new file mode 100644
index 000000000..1e60848ec
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/local/connect_pair.cpp
@@ -0,0 +1,130 @@
+//
+// connect_pair.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <string>
+#include <cctype>
+#include <boost/asio.hpp>
+#include <boost/thread/thread.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+
+using boost::asio::local::stream_protocol;
+
+class uppercase_filter
+{
+public:
+ uppercase_filter(stream_protocol::socket sock)
+ : socket_(std::move(sock))
+ {
+ read();
+ }
+
+private:
+ void read()
+ {
+ socket_.async_read_some(boost::asio::buffer(data_),
+ [this](boost::system::error_code ec, std::size_t size)
+ {
+ if (!ec)
+ {
+ // Compute result.
+ for (std::size_t i = 0; i < size; ++i)
+ data_[i] = std::toupper(data_[i]);
+
+ // Send result.
+ write(size);
+ }
+ else
+ {
+ throw boost::system::system_error(ec);
+ }
+ });
+ }
+
+ void write(std::size_t size)
+ {
+ boost::asio::async_write(socket_, boost::asio::buffer(data_, size),
+ [this](boost::system::error_code ec, std::size_t /*size*/)
+ {
+ if (!ec)
+ {
+ // Wait for request.
+ read();
+ }
+ else
+ {
+ throw boost::system::system_error(ec);
+ }
+ });
+ }
+
+ stream_protocol::socket socket_;
+ std::array<char, 512> data_;
+};
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context;
+
+ // Create a connected pair and pass one end to a filter.
+ stream_protocol::socket socket(io_context);
+ stream_protocol::socket filter_socket(io_context);
+ boost::asio::local::connect_pair(socket, filter_socket);
+ uppercase_filter filter(std::move(filter_socket));
+
+ // The io_context runs in a background thread to perform filtering.
+ boost::thread thread(
+ [&io_context]()
+ {
+ try
+ {
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception in thread: " << e.what() << "\n";
+ std::exit(1);
+ }
+ });
+
+ for (;;)
+ {
+ // Collect request from user.
+ std::cout << "Enter a string: ";
+ std::string request;
+ std::getline(std::cin, request);
+
+ // Send request to filter.
+ boost::asio::write(socket, boost::asio::buffer(request));
+
+ // Wait for reply from filter.
+ std::vector<char> reply(request.size());
+ boost::asio::read(socket, boost::asio::buffer(reply));
+
+ // Show reply to user.
+ std::cout << "Result: ";
+ std::cout.write(&reply[0], request.size());
+ std::cout << std::endl;
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ std::exit(1);
+ }
+}
+
+#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+# error Local sockets not available on this platform.
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
diff --git a/src/boost/libs/asio/example/cpp11/local/iostream_client.cpp b/src/boost/libs/asio/example/cpp11/local/iostream_client.cpp
new file mode 100644
index 000000000..2bc79e81b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/local/iostream_client.cpp
@@ -0,0 +1,61 @@
+//
+// stream_client.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstring>
+#include <iostream>
+#include <boost/asio.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+
+using boost::asio::local::stream_protocol;
+
+constexpr std::size_t max_length = 1024;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: iostream_client <file>\n";
+ return 1;
+ }
+
+ stream_protocol::endpoint ep(argv[1]);
+ stream_protocol::iostream s(ep);
+ if (!s)
+ {
+ std::cerr << "Unable to connect: " << s.error().message() << std::endl;
+ return 1;
+ }
+
+ std::cout << "Enter message: ";
+ char request[max_length];
+ std::cin.getline(request, max_length);
+ size_t length = std::strlen(request);
+ s << request;
+
+ char reply[max_length];
+ s.read(reply, length);
+ std::cout << "Reply is: ";
+ std::cout.write(reply, length);
+ std::cout << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
+
+#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+# error Local sockets not available on this platform.
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
diff --git a/src/boost/libs/asio/example/cpp11/local/stream_client.cpp b/src/boost/libs/asio/example/cpp11/local/stream_client.cpp
new file mode 100644
index 000000000..5d03adb50
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/local/stream_client.cpp
@@ -0,0 +1,60 @@
+//
+// stream_client.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <boost/asio.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+
+using boost::asio::local::stream_protocol;
+
+constexpr std::size_t max_length = 1024;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: stream_client <file>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ stream_protocol::socket s(io_context);
+ s.connect(stream_protocol::endpoint(argv[1]));
+
+ std::cout << "Enter message: ";
+ char request[max_length];
+ std::cin.getline(request, max_length);
+ size_t request_length = std::strlen(request);
+ boost::asio::write(s, boost::asio::buffer(request, request_length));
+
+ char reply[max_length];
+ size_t reply_length = boost::asio::read(s,
+ boost::asio::buffer(reply, request_length));
+ std::cout << "Reply is: ";
+ std::cout.write(reply, reply_length);
+ std::cout << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
+
+#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+# error Local sockets not available on this platform.
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
diff --git a/src/boost/libs/asio/example/cpp11/local/stream_server.cpp b/src/boost/libs/asio/example/cpp11/local/stream_server.cpp
new file mode 100644
index 000000000..6b915029e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/local/stream_server.cpp
@@ -0,0 +1,121 @@
+//
+// stream_server.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdio>
+#include <iostream>
+#include <memory>
+#include <boost/asio.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+
+using boost::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(boost::asio::buffer(data_),
+ [this, self](boost::system::error_code ec, std::size_t length)
+ {
+ if (!ec)
+ do_write(length);
+ });
+ }
+
+ void do_write(std::size_t length)
+ {
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(data_, length),
+ [this, self](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec)
+ 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(boost::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](boost::system::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: stream_server <file>\n";
+ std::cerr << "*** WARNING: existing file is removed ***\n";
+ return 1;
+ }
+
+ boost::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(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+# error Local sockets not available on this platform.
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
diff --git a/src/boost/libs/asio/example/cpp11/multicast/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/multicast/Jamfile.v2
new file mode 100644
index 000000000..dbfe4f47b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/multicast/Jamfile.v2
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe receiver : receiver.cpp ;
+exe sender : sender.cpp ;
diff --git a/src/boost/libs/asio/example/cpp11/multicast/receiver.cpp b/src/boost/libs/asio/example/cpp11/multicast/receiver.cpp
new file mode 100644
index 000000000..7148288b8
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/multicast/receiver.cpp
@@ -0,0 +1,88 @@
+//
+// receiver.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <string>
+#include <boost/asio.hpp>
+
+constexpr short multicast_port = 30001;
+
+class receiver
+{
+public:
+ receiver(boost::asio::io_context& io_context,
+ const boost::asio::ip::address& listen_address,
+ const boost::asio::ip::address& multicast_address)
+ : socket_(io_context)
+ {
+ // Create the socket so that multiple may be bound to the same address.
+ boost::asio::ip::udp::endpoint listen_endpoint(
+ listen_address, multicast_port);
+ socket_.open(listen_endpoint.protocol());
+ socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
+ socket_.bind(listen_endpoint);
+
+ // Join the multicast group.
+ socket_.set_option(
+ boost::asio::ip::multicast::join_group(multicast_address));
+
+ do_receive();
+ }
+
+private:
+ void do_receive()
+ {
+ socket_.async_receive_from(
+ boost::asio::buffer(data_), sender_endpoint_,
+ [this](boost::system::error_code ec, std::size_t length)
+ {
+ if (!ec)
+ {
+ std::cout.write(data_.data(), length);
+ std::cout << std::endl;
+
+ do_receive();
+ }
+ });
+ }
+
+ boost::asio::ip::udp::socket socket_;
+ boost::asio::ip::udp::endpoint sender_endpoint_;
+ std::array<char, 1024> data_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: receiver <listen_address> <multicast_address>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " receiver 0.0.0.0 239.255.0.1\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " receiver 0::0 ff31::8000:1234\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+ receiver r(io_context,
+ boost::asio::ip::make_address(argv[1]),
+ boost::asio::ip::make_address(argv[2]));
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/multicast/sender.cpp b/src/boost/libs/asio/example/cpp11/multicast/sender.cpp
new file mode 100644
index 000000000..92312a71a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/multicast/sender.cpp
@@ -0,0 +1,91 @@
+//
+// sender.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <sstream>
+#include <string>
+#include <boost/asio.hpp>
+
+constexpr short multicast_port = 30001;
+constexpr int max_message_count = 10;
+
+class sender
+{
+public:
+ sender(boost::asio::io_context& io_context,
+ const boost::asio::ip::address& multicast_address)
+ : endpoint_(multicast_address, multicast_port),
+ socket_(io_context, endpoint_.protocol()),
+ timer_(io_context),
+ message_count_(0)
+ {
+ do_send();
+ }
+
+private:
+ void do_send()
+ {
+ std::ostringstream os;
+ os << "Message " << message_count_++;
+ message_ = os.str();
+
+ socket_.async_send_to(
+ boost::asio::buffer(message_), endpoint_,
+ [this](boost::system::error_code ec, std::size_t /*length*/)
+ {
+ if (!ec && message_count_ < max_message_count)
+ do_timeout();
+ });
+ }
+
+ void do_timeout()
+ {
+ timer_.expires_after(std::chrono::seconds(1));
+ timer_.async_wait(
+ [this](boost::system::error_code ec)
+ {
+ if (!ec)
+ do_send();
+ });
+ }
+
+private:
+ boost::asio::ip::udp::endpoint endpoint_;
+ boost::asio::ip::udp::socket socket_;
+ boost::asio::steady_timer timer_;
+ int message_count_;
+ std::string message_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: sender <multicast_address>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " sender 239.255.0.1\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " sender ff31::8000:1234\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+ sender s(io_context, boost::asio::ip::make_address(argv[1]));
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/nonblocking/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/nonblocking/Jamfile.v2
new file mode 100644
index 000000000..1ef265c4f
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/nonblocking/Jamfile.v2
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe third_party_lib
+ : third_party_lib.cpp
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/nonblocking/third_party_lib.cpp b/src/boost/libs/asio/example/cpp11/nonblocking/third_party_lib.cpp
new file mode 100644
index 000000000..ceea0e61e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/nonblocking/third_party_lib.cpp
@@ -0,0 +1,212 @@
+//
+// third_party_lib.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <array>
+#include <iostream>
+#include <memory>
+
+using boost::asio::ip::tcp;
+
+namespace third_party_lib {
+
+// Simulation of a third party library that wants to perform read and write
+// operations directly on a socket. It needs to be polled to determine whether
+// it requires a read or write operation, and notified when the socket is ready
+// for reading or writing.
+class session
+{
+public:
+ session(tcp::socket& socket)
+ : socket_(socket)
+ {
+ }
+
+ // Returns true if the third party library wants to be notified when the
+ // socket is ready for reading.
+ bool want_read() const
+ {
+ return state_ == reading;
+ }
+
+ // Notify that third party library that it should perform its read operation.
+ void do_read(boost::system::error_code& ec)
+ {
+ if (std::size_t len = socket_.read_some(boost::asio::buffer(data_), ec))
+ {
+ write_buffer_ = boost::asio::buffer(data_, len);
+ state_ = writing;
+ }
+ }
+
+ // Returns true if the third party library wants to be notified when the
+ // socket is ready for writing.
+ bool want_write() const
+ {
+ return state_ == writing;
+ }
+
+ // Notify that third party library that it should perform its write operation.
+ void do_write(boost::system::error_code& ec)
+ {
+ if (std::size_t len = socket_.write_some(
+ boost::asio::buffer(write_buffer_), ec))
+ {
+ write_buffer_ = write_buffer_ + len;
+ state_ = boost::asio::buffer_size(write_buffer_) > 0 ? writing : reading;
+ }
+ }
+
+private:
+ tcp::socket& socket_;
+ enum { reading, writing } state_ = reading;
+ std::array<char, 128> data_;
+ boost::asio::const_buffer write_buffer_;
+};
+
+} // namespace third_party_lib
+
+// The glue between asio's sockets and the third party library.
+class connection
+ : public std::enable_shared_from_this<connection>
+{
+public:
+ connection(tcp::socket socket)
+ : socket_(std::move(socket))
+ {
+ }
+
+ void start()
+ {
+ // Put the socket into non-blocking mode.
+ socket_.non_blocking(true);
+
+ do_operations();
+ }
+
+private:
+ void do_operations()
+ {
+ auto self(shared_from_this());
+
+ // Start a read operation if the third party library wants one.
+ if (session_impl_.want_read() && !read_in_progress_)
+ {
+ read_in_progress_ = true;
+ socket_.async_wait(tcp::socket::wait_read,
+ [this, self](boost::system::error_code ec)
+ {
+ read_in_progress_ = false;
+
+ // Notify third party library that it can perform a read.
+ if (!ec)
+ session_impl_.do_read(ec);
+
+ // The third party library successfully performed a read on the
+ // socket. Start new read or write operations based on what it now
+ // wants.
+ if (!ec || ec == boost::asio::error::would_block)
+ do_operations();
+
+ // Otherwise, an error occurred. Closing the socket cancels any
+ // outstanding asynchronous read or write operations. The
+ // connection object will be destroyed automatically once those
+ // outstanding operations complete.
+ else
+ socket_.close();
+ });
+ }
+
+ // Start a write operation if the third party library wants one.
+ if (session_impl_.want_write() && !write_in_progress_)
+ {
+ write_in_progress_ = true;
+ socket_.async_wait(tcp::socket::wait_write,
+ [this, self](boost::system::error_code ec)
+ {
+ write_in_progress_ = false;
+
+ // Notify third party library that it can perform a write.
+ if (!ec)
+ session_impl_.do_write(ec);
+
+ // The third party library successfully performed a write on the
+ // socket. Start new read or write operations based on what it now
+ // wants.
+ if (!ec || ec == boost::asio::error::would_block)
+ do_operations();
+
+ // Otherwise, an error occurred. Closing the socket cancels any
+ // outstanding asynchronous read or write operations. The
+ // connection object will be destroyed automatically once those
+ // outstanding operations complete.
+ else
+ socket_.close();
+ });
+ }
+ }
+
+private:
+ tcp::socket socket_;
+ third_party_lib::session session_impl_{socket_};
+ bool read_in_progress_ = false;
+ bool write_in_progress_ = false;
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, unsigned short port)
+ : acceptor_(io_context, {tcp::v4(), port})
+ {
+ do_accept();
+ }
+
+private:
+ void do_accept()
+ {
+ acceptor_.async_accept(
+ [this](boost::system::error_code ec, tcp::socket socket)
+ {
+ if (!ec)
+ {
+ std::make_shared<connection>(std::move(socket))->start();
+ }
+
+ do_accept();
+ });
+ }
+
+ tcp::acceptor acceptor_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: third_party_lib <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ server s(io_context, std::atoi(argv[1]));
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/operations/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/operations/Jamfile.v2
new file mode 100644
index 000000000..a01b42a3a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/Jamfile.v2
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe composed_1 : composed_1.cpp ;
+exe composed_2 : composed_2.cpp ;
+exe composed_3 : composed_3.cpp ;
+exe composed_4 : composed_4.cpp ;
+exe composed_5 : composed_5.cpp ;
+exe composed_6 : composed_6.cpp ;
+exe composed_7 : composed_7.cpp ;
+exe composed_8 : composed_8.cpp ;
diff --git a/src/boost/libs/asio/example/cpp11/operations/composed_1.cpp b/src/boost/libs/asio/example/cpp11/operations/composed_1.cpp
new file mode 100644
index 000000000..31906d006
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/composed_1.cpp
@@ -0,0 +1,113 @@
+//
+// composed_1.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+//------------------------------------------------------------------------------
+
+// This is the simplest example of a composed asynchronous operation, where we
+// simply repackage an existing operation. The asynchronous operation
+// requirements are met by delegating responsibility to the underlying
+// operation.
+
+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 boost::asio::yield_context (used for stackful
+ // coroutines) the return type would be std::size_t, and when the completion
+ // token is boost::asio::use_future it would be std::future<std::size_t>.
+ -> typename boost::asio::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(boost::system::error_code, std::size_t)>::return_type
+{
+ // When delegating to the 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 boost::asio::async_write(socket,
+ boost::asio::buffer(message, std::strlen(message)),
+ std::forward<CompletionToken>(token));
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, "Testing callback\r\n",
+ [](const boost::system::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()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<std::size_t> f = async_write_message(
+ socket, "Testing future\r\n", boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ std::size_t n = f.get();
+ std::cout << n << " bytes transferred\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp11/operations/composed_2.cpp b/src/boost/libs/asio/example/cpp11/operations/composed_2.cpp
new file mode 100644
index 000000000..1d0656725
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/composed_2.cpp
@@ -0,0 +1,131 @@
+//
+// composed_2.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+//------------------------------------------------------------------------------
+
+// This next simplest example of a composed asynchronous operation involves
+// repackaging multiple operations but choosing to invoke just one of them. All
+// of these underlying operations have the same completion signature. The
+// asynchronous operation requirements are met by delegating responsibility to
+// the underlying operations.
+
+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 boost::asio::yield_context (used for stackful
+ // coroutines) the return type would be std::size_t, and when the completion
+ // token is boost::asio::use_future it would be std::future<std::size_t>.
+ -> typename boost::asio::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(boost::system::error_code, std::size_t)>::return_type
+{
+ // 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(
+ boost::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 boost::asio::async_write(socket,
+ boost::asio::buffer(message, std::strlen(message)),
+ std::forward<CompletionToken>(token));
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, "Testing callback\r\n", false,
+ [](const boost::system::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()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<std::size_t> f = async_write_message(
+ socket, "Testing future\r\n", false, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ std::size_t n = f.get();
+ std::cout << n << " bytes transferred\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp11/operations/composed_3.cpp b/src/boost/libs/asio/example/cpp11/operations/composed_3.cpp
new file mode 100644
index 000000000..563db94fa
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/composed_3.cpp
@@ -0,0 +1,192 @@
+//
+// composed_3.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/bind_executor.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::asio::async_initiate function. For
+// an example that works with the Networking TS style of completion tokens,
+// please see an older version of asio.
+
+//------------------------------------------------------------------------------
+
+// In this composed operation we repackage an existing operation, but with a
+// different completion handler signature. The asynchronous operation
+// requirements are met by delegating responsibility to the underlying
+// operation.
+
+// 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(boost::system::error_code error)
+ //
+ // 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) const
+ {
+ // The async_write operation has a completion handler signature of:
+ //
+ // void(boost::system::error_code error, std::size n)
+ //
+ // This differs from our operation's signature in that it is also passed
+ // the number of bytes transferred as an argument of type std::size_t. We
+ // will adapt our completion handler to async_write's completion handler
+ // signature by using std::bind, which drops the additional argument.
+ //
+ // However, it is essential to the correctness of our composed operation
+ // that we preserve the executor of the user-supplied completion handler.
+ // The std::bind function will not do this for us, so we must do this by
+ // first obtaining the completion handler's associated executor (defaulting
+ // to the I/O executor - in this case the executor of the socket - if the
+ // completion handler does not have its own) ...
+ auto executor = boost::asio::get_associated_executor(
+ completion_handler, socket.get_executor());
+
+ // ... and then binding this executor to our adapted completion handler
+ // using the boost::asio::bind_executor function.
+ boost::asio::async_write(socket,
+ boost::asio::buffer(message, std::strlen(message)),
+ boost::asio::bind_executor(executor,
+ std::bind(std::forward<CompletionHandler>(
+ completion_handler), std::placeholders::_1)));
+ }
+};
+
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ -> typename boost::asio::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(boost::system::error_code)>::return_type
+{
+ // The boost::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 boost::asio::async_initiate<
+ CompletionToken, void(boost::system::error_code)>(
+ async_write_message_initiation(),
+ token, std::ref(socket), message);
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, "Testing callback\r\n",
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Message sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_message(
+ socket, "Testing future\r\n", boost::asio::use_future);
+
+ io_context.run();
+
+ // Get the result of the operation.
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Message sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp11/operations/composed_4.cpp b/src/boost/libs/asio/example/cpp11/operations/composed_4.cpp
new file mode 100644
index 000000000..cd70684ff
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/composed_4.cpp
@@ -0,0 +1,207 @@
+//
+// composed_4.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/bind_executor.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::asio::async_initiate function. For
+// an example that works with the Networking TS style of completion tokens,
+// please see an older version of asio.
+
+//------------------------------------------------------------------------------
+
+// In this composed operation we repackage an existing operation, but with a
+// different completion handler signature. We will also intercept an empty
+// message as an invalid argument, and propagate the corresponding error to the
+// user. The asynchronous operation requirements are met by delegating
+// responsibility to the underlying operation.
+
+// 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(boost::system::error_code error)
+ //
+ // 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) const
+ {
+ // The post operation has a completion handler signature of:
+ //
+ // void()
+ //
+ // and the async_write operation has a completion handler signature of:
+ //
+ // void(boost::system::error_code error, std::size n)
+ //
+ // Both of these operations' completion handler signatures differ from our
+ // operation's completion handler signature. We will adapt our completion
+ // handler to these signatures by using std::bind, which drops the
+ // additional arguments.
+ //
+ // However, it is essential to the correctness of our composed operation
+ // that we preserve the executor of the user-supplied completion handler.
+ // The std::bind function will not do this for us, so we must do this by
+ // first obtaining the completion handler's associated executor (defaulting
+ // to the I/O executor - in this case the executor of the socket - if the
+ // completion handler does not have its own) ...
+ auto executor = boost::asio::get_associated_executor(
+ completion_handler, socket.get_executor());
+
+ // ... and then binding this executor to our adapted completion handler
+ // using the boost::asio::bind_executor function.
+ std::size_t length = std::strlen(message);
+ if (length == 0)
+ {
+ boost::asio::post(
+ boost::asio::bind_executor(executor,
+ std::bind(std::forward<CompletionHandler>(completion_handler),
+ boost::asio::error::invalid_argument)));
+ }
+ else
+ {
+ boost::asio::async_write(socket,
+ boost::asio::buffer(message, length),
+ boost::asio::bind_executor(executor,
+ std::bind(std::forward<CompletionHandler>(completion_handler),
+ std::placeholders::_1)));
+ }
+ }
+};
+
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ -> typename boost::asio::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(boost::system::error_code)>::return_type
+{
+ // The boost::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 boost::asio::async_initiate<
+ CompletionToken, void(boost::system::error_code)>(
+ async_write_message_initiation(),
+ token, std::ref(socket), message);
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, "",
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Message sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_message(
+ socket, "", boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Message sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp11/operations/composed_5.cpp b/src/boost/libs/asio/example/cpp11/operations/composed_5.cpp
new file mode 100644
index 000000000..2f5f823a3
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/composed_5.cpp
@@ -0,0 +1,243 @@
+//
+// composed_5.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::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 composed operation automatically serialises a message, using its I/O
+// streams insertion operator, before sending it on the socket. To do this, it
+// must allocate a buffer for the encoded message and ensure this buffer's
+// validity until the underlying async_write operation completes.
+
+// 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(boost::system::error_code error)
+ //
+ // 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, std::unique_ptr<std::string> encoded_message) const
+ {
+ // In this example, the composed operation's intermediate completion
+ // handler is implemented as a hand-crafted function object, rather than
+ // using a lambda or std::bind.
+ struct intermediate_completion_handler
+ {
+ // The intermediate completion handler holds a reference to the socket so
+ // that it can obtain the I/O executor (see get_executor below).
+ tcp::socket& socket_;
+
+ // The allocated buffer for the encoded message. The std::unique_ptr
+ // smart pointer is move-only, and as a consequence our intermediate
+ // completion handler is also move-only.
+ std::unique_ptr<std::string> encoded_message_;
+
+ // The user-supplied completion handler.
+ typename std::decay<CompletionHandler>::type handler_;
+
+ // The function call operator matches the completion signature of the
+ // async_write operation.
+ void operator()(const boost::system::error_code& error, std::size_t /*n*/)
+ {
+ // Deallocate the encoded message before calling the user-supplied
+ // completion handler.
+ encoded_message_.reset();
+
+ // Call the user-supplied handler with the result of the operation.
+ // The arguments must match the completion signature of our composed
+ // operation.
+ handler_(error);
+ }
+
+ // It is essential to the correctness of our composed operation that we
+ // preserve the executor of the user-supplied completion handler. With a
+ // hand-crafted function object we can do this by defining a nested type
+ // executor_type and member function get_executor. These obtain the
+ // completion handler's associated executor, and default to the I/O
+ // executor - in this case the executor of the socket - if the completion
+ // handler does not have its own.
+ using executor_type = boost::asio::associated_executor_t<
+ typename std::decay<CompletionHandler>::type,
+ tcp::socket::executor_type>;
+
+ executor_type get_executor() const noexcept
+ {
+ return boost::asio::get_associated_executor(
+ handler_, socket_.get_executor());
+ }
+
+ // Although not necessary for correctness, we may also preserve the
+ // allocator of the user-supplied completion handler. This is achieved by
+ // defining a nested type allocator_type and member function
+ // get_allocator. These obtain the completion handler's associated
+ // allocator, and default to std::allocator<void> if the completion
+ // handler does not have its own.
+ using allocator_type = boost::asio::associated_allocator_t<
+ typename std::decay<CompletionHandler>::type,
+ std::allocator<void>>;
+
+ allocator_type get_allocator() const noexcept
+ {
+ return boost::asio::get_associated_allocator(
+ handler_, std::allocator<void>{});
+ }
+ };
+
+ // Initiate the underlying async_write operation using our intermediate
+ // completion handler.
+ auto encoded_message_buffer = boost::asio::buffer(*encoded_message);
+ boost::asio::async_write(socket, encoded_message_buffer,
+ intermediate_completion_handler{socket, std::move(encoded_message),
+ std::forward<CompletionHandler>(completion_handler)});
+ }
+};
+
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ -> typename boost::asio::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(boost::system::error_code)>::return_type
+{
+ // Encode the message and copy it into an allocated buffer. The buffer will
+ // be maintained for the lifetime of the asynchronous operation.
+ std::ostringstream os;
+ os << message;
+ std::unique_ptr<std::string> encoded_message(new std::string(os.str()));
+
+ // The boost::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 boost::asio::async_initiate<
+ CompletionToken, void(boost::system::error_code)>(
+ async_write_message_initiation(), token,
+ std::ref(socket), std::move(encoded_message));
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, 123456,
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Message sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_message(
+ socket, 654.321, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Message sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp11/operations/composed_6.cpp b/src/boost/libs/asio/example/cpp11/operations/composed_6.cpp
new file mode 100644
index 000000000..d3a51fc78
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/composed_6.cpp
@@ -0,0 +1,302 @@
+//
+// composed_6.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::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 composed operation shows composition of multiple underlying operations.
+// It automatically serialises a message, using its I/O streams insertion
+// operator, before sending it N times on the socket. To do this, it must
+// allocate a buffer for the encoded message and ensure this buffer's validity
+// until all underlying async_write operation complete. A one second delay is
+// inserted prior to each write operation, using a steady_timer.
+
+// 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(boost::system::error_code error)
+ //
+ // 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,
+ std::unique_ptr<std::string> encoded_message, std::size_t repeat_count,
+ std::unique_ptr<boost::asio::steady_timer> delay_timer) const
+ {
+ // In this example, the composed operation's intermediate completion
+ // handler is implemented as a hand-crafted function object.
+ struct intermediate_completion_handler
+ {
+ // The intermediate completion handler holds a reference to the socket as
+ // it is used for multiple async_write operations, as well as for
+ // obtaining the I/O executor (see get_executor below).
+ tcp::socket& socket_;
+
+ // The allocated buffer for the encoded message. The std::unique_ptr
+ // smart pointer is move-only, and as a consequence our intermediate
+ // completion handler is also move-only.
+ std::unique_ptr<std::string> encoded_message_;
+
+ // The repeat count remaining.
+ std::size_t repeat_count_;
+
+ // A steady timer used for introducing a delay.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer_;
+
+ // To manage the cycle between the multiple underlying asychronous
+ // operations, our intermediate completion handler is implemented as a
+ // state machine.
+ enum { starting, waiting, writing } state_;
+
+ // 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.
+ boost::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.
+ typename std::decay<CompletionHandler>::type handler_;
+
+ // By having a default value for the second argument, this function call
+ // operator matches the completion signature of both the async_write and
+ // steady_timer::async_wait operations.
+ void operator()(const boost::system::error_code& error, std::size_t = 0)
+ {
+ if (!error)
+ {
+ switch (state_)
+ {
+ case starting:
+ case writing:
+ if (repeat_count_ > 0)
+ {
+ --repeat_count_;
+ state_ = waiting;
+ delay_timer_->expires_after(std::chrono::seconds(1));
+ delay_timer_->async_wait(std::move(*this));
+ return; // Composed operation not yet complete.
+ }
+ break; // Composed operation complete, continue below.
+ case waiting:
+ state_ = writing;
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(*encoded_message_), std::move(*this));
+ return; // Composed operation not yet complete.
+ }
+ }
+
+ // 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();
+
+ // Call the user-supplied handler with the result of the operation.
+ handler_(error);
+ }
+
+ // It is essential to the correctness of our composed operation that we
+ // preserve the executor of the user-supplied completion handler. With a
+ // hand-crafted function object we can do this by defining a nested type
+ // executor_type and member function get_executor. These obtain the
+ // completion handler's associated executor, and default to the I/O
+ // executor - in this case the executor of the socket - if the completion
+ // handler does not have its own.
+ using executor_type = boost::asio::associated_executor_t<
+ typename std::decay<CompletionHandler>::type,
+ tcp::socket::executor_type>;
+
+ executor_type get_executor() const noexcept
+ {
+ return boost::asio::get_associated_executor(
+ handler_, socket_.get_executor());
+ }
+
+ // Although not necessary for correctness, we may also preserve the
+ // allocator of the user-supplied completion handler. This is achieved by
+ // defining a nested type allocator_type and member function
+ // get_allocator. These obtain the completion handler's associated
+ // allocator, and default to std::allocator<void> if the completion
+ // handler does not have its own.
+ using allocator_type = boost::asio::associated_allocator_t<
+ typename std::decay<CompletionHandler>::type,
+ std::allocator<void>>;
+
+ allocator_type get_allocator() const noexcept
+ {
+ return boost::asio::get_associated_allocator(
+ handler_, std::allocator<void>{});
+ }
+ };
+
+ // Initiate the underlying async_write operation using our intermediate
+ // completion handler.
+ auto encoded_message_buffer = boost::asio::buffer(*encoded_message);
+ boost::asio::async_write(socket, encoded_message_buffer,
+ intermediate_completion_handler{
+ socket, std::move(encoded_message),
+ repeat_count, std::move(delay_timer),
+ intermediate_completion_handler::starting,
+ boost::asio::make_work_guard(socket.get_executor()),
+ std::forward<CompletionHandler>(completion_handler)});
+ }
+};
+
+template <typename T, typename CompletionToken>
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ -> typename boost::asio::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(boost::system::error_code)>::return_type
+{
+ // Encode the message and copy it into an allocated buffer. The buffer will
+ // be maintained for the lifetime of the composed asynchronous operation.
+ std::ostringstream os;
+ os << message;
+ std::unique_ptr<std::string> encoded_message(new std::string(os.str()));
+
+ // Create a steady_timer to be used for the delay between messages.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer(
+ new boost::asio::steady_timer(socket.get_executor()));
+
+ // The boost::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 boost::asio::async_initiate<
+ CompletionToken, void(boost::system::error_code)>(
+ async_write_message_initiation(), token, std::ref(socket),
+ std::move(encoded_message), repeat_count, std::move(delay_timer));
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_messages(socket, "Testing callback\r\n", 5,
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Messages sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_messages(
+ socket, "Testing future\r\n", 5, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Messages sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp11/operations/composed_7.cpp b/src/boost/libs/asio/example/cpp11/operations/composed_7.cpp
new file mode 100644
index 000000000..1139c2d39
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/composed_7.cpp
@@ -0,0 +1,222 @@
+//
+// composed_7.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/compose.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::asio::async_compose function. For
+// an example that works with the Networking TS style of completion tokens,
+// please see an older version of asio.
+
+//------------------------------------------------------------------------------
+
+// This composed operation shows composition of multiple underlying operations.
+// It automatically serialises a message, using its I/O streams insertion
+// operator, before sending it N times on the socket. To do this, it must
+// allocate a buffer for the encoded message and ensure this buffer's validity
+// until all underlying async_write operation complete. A one second delay is
+// inserted prior to each write operation, using a steady_timer.
+
+// In this example, the composed operation's logic is implemented as a state
+// machine within a hand-crafted function object.
+struct async_write_messages_implementation
+{
+ // The implementation holds a reference to the socket as it is used for
+ // multiple async_write operations.
+ tcp::socket& socket_;
+
+ // The allocated buffer for the encoded message. The std::unique_ptr smart
+ // pointer is move-only, and as a consequence our implementation is also
+ // move-only.
+ std::unique_ptr<std::string> encoded_message_;
+
+ // The repeat count remaining.
+ std::size_t repeat_count_;
+
+ // A steady timer used for introducing a delay.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer_;
+
+ // To manage the cycle between the multiple underlying asychronous
+ // operations, our implementation is a state machine.
+ enum { starting, waiting, writing } state_;
+
+ // The first argument to our function object's call operator is a reference
+ // to the enclosing intermediate completion handler. This intermediate
+ // completion handler is provided for us by the boost::asio::async_compose
+ // function, and takes care of all the details required to implement a
+ // conforming asynchronous operation. When calling an underlying asynchronous
+ // operation, we pass it this enclosing intermediate completion handler
+ // as the completion token.
+ //
+ // All arguments after the first must be defaulted to allow the state machine
+ // to be started, as well as to allow the completion handler to match the
+ // completion signature of both the async_write and steady_timer::async_wait
+ // operations.
+ template <typename Self>
+ void operator()(Self& self,
+ const boost::system::error_code& error = boost::system::error_code(),
+ std::size_t = 0)
+ {
+ if (!error)
+ {
+ switch (state_)
+ {
+ case starting:
+ case writing:
+ if (repeat_count_ > 0)
+ {
+ --repeat_count_;
+ state_ = waiting;
+ delay_timer_->expires_after(std::chrono::seconds(1));
+ delay_timer_->async_wait(std::move(self));
+ return; // Composed operation not yet complete.
+ }
+ break; // Composed operation complete, continue below.
+ case waiting:
+ state_ = writing;
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(*encoded_message_), std::move(self));
+ return; // Composed operation not yet complete.
+ }
+ }
+
+ // This point is reached only on completion of the entire composed
+ // operation.
+
+ // Deallocate the encoded message and delay timer before calling the
+ // user-supplied completion handler.
+ encoded_message_.reset();
+ delay_timer_.reset();
+
+ // Call the user-supplied handler with the result of the operation.
+ self.complete(error);
+ }
+};
+
+template <typename T, typename CompletionToken>
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ -> typename boost::asio::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(boost::system::error_code)>::return_type
+{
+ // Encode the message and copy it into an allocated buffer. The buffer will
+ // be maintained for the lifetime of the composed asynchronous operation.
+ std::ostringstream os;
+ os << message;
+ std::unique_ptr<std::string> encoded_message(new std::string(os.str()));
+
+ // Create a steady_timer to be used for the delay between messages.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer(
+ new boost::asio::steady_timer(socket.get_executor()));
+
+ // The boost::asio::async_compose function takes:
+ //
+ // - our asynchronous operation implementation,
+ // - the completion token,
+ // - the completion handler signature, and
+ // - any I/O objects (or executors) used by the operation
+ //
+ // It then wraps our implementation in an intermediate completion handler
+ // that meets the requirements of a conforming asynchronous operation. This
+ // includes tracking outstanding work against the I/O executors associated
+ // with the operation (in this example, this is the socket's executor).
+ return boost::asio::async_compose<
+ CompletionToken, void(boost::system::error_code)>(
+ async_write_messages_implementation{
+ socket, std::move(encoded_message),
+ repeat_count, std::move(delay_timer),
+ async_write_messages_implementation::starting},
+ token, socket);
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_messages(socket, "Testing callback\r\n", 5,
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Messages sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_messages(
+ socket, "Testing future\r\n", 5, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Messages sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp11/operations/composed_8.cpp b/src/boost/libs/asio/example/cpp11/operations/composed_8.cpp
new file mode 100644
index 000000000..4fb684656
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/operations/composed_8.cpp
@@ -0,0 +1,217 @@
+//
+// composed_8.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/compose.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::asio::async_compose function. For
+// an example that works with the Networking TS style of completion tokens,
+// please see an older version of asio.
+
+//------------------------------------------------------------------------------
+
+// This composed operation shows composition of multiple underlying operations,
+// using asio's stackless coroutines support to express the flow of control. It
+// automatically serialises a message, using its I/O streams insertion
+// operator, before sending it N times on the socket. To do this, it must
+// allocate a buffer for the encoded message and ensure this buffer's validity
+// until all underlying async_write operation complete. A one second delay is
+// inserted prior to each write operation, using a steady_timer.
+
+#include <boost/asio/yield.hpp>
+
+// In this example, the composed operation's logic is implemented as a state
+// machine within a hand-crafted function object.
+struct async_write_messages_implementation
+{
+ // The implementation holds a reference to the socket as it is used for
+ // multiple async_write operations.
+ tcp::socket& socket_;
+
+ // The allocated buffer for the encoded message. The std::unique_ptr smart
+ // pointer is move-only, and as a consequence our implementation is also
+ // move-only.
+ std::unique_ptr<std::string> encoded_message_;
+
+ // The repeat count remaining.
+ std::size_t repeat_count_;
+
+ // A steady timer used for introducing a delay.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer_;
+
+ // The coroutine state.
+ boost::asio::coroutine coro_;
+
+ // The first argument to our function object's call operator is a reference
+ // to the enclosing intermediate completion handler. This intermediate
+ // completion handler is provided for us by the boost::asio::async_compose
+ // function, and takes care of all the details required to implement a
+ // conforming asynchronous operation. When calling an underlying asynchronous
+ // operation, we pass it this enclosing intermediate completion handler
+ // as the completion token.
+ //
+ // All arguments after the first must be defaulted to allow the state machine
+ // to be started, as well as to allow the completion handler to match the
+ // completion signature of both the async_write and steady_timer::async_wait
+ // operations.
+ template <typename Self>
+ void operator()(Self& self,
+ const boost::system::error_code& error = boost::system::error_code(),
+ std::size_t = 0)
+ {
+ reenter (coro_)
+ {
+ while (repeat_count_ > 0)
+ {
+ --repeat_count_;
+
+ delay_timer_->expires_after(std::chrono::seconds(1));
+ yield delay_timer_->async_wait(std::move(self));
+ if (error)
+ break;
+
+ yield boost::asio::async_write(socket_,
+ boost::asio::buffer(*encoded_message_), std::move(self));
+ if (error)
+ break;
+ }
+
+ // Deallocate the encoded message and delay timer before calling the
+ // user-supplied completion handler.
+ encoded_message_.reset();
+ delay_timer_.reset();
+
+ // Call the user-supplied handler with the result of the operation.
+ self.complete(error);
+ }
+ }
+};
+
+#include <boost/asio/unyield.hpp>
+
+template <typename T, typename CompletionToken>
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ -> typename boost::asio::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(boost::system::error_code)>::return_type
+{
+ // Encode the message and copy it into an allocated buffer. The buffer will
+ // be maintained for the lifetime of the composed asynchronous operation.
+ std::ostringstream os;
+ os << message;
+ std::unique_ptr<std::string> encoded_message(new std::string(os.str()));
+
+ // Create a steady_timer to be used for the delay between messages.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer(
+ new boost::asio::steady_timer(socket.get_executor()));
+
+ // The boost::asio::async_compose function takes:
+ //
+ // - our asynchronous operation implementation,
+ // - the completion token,
+ // - the completion handler signature, and
+ // - any I/O objects (or executors) used by the operation
+ //
+ // It then wraps our implementation in an intermediate completion handler
+ // that meets the requirements of a conforming asynchronous operation. This
+ // includes tracking outstanding work against the I/O executors associated
+ // with the operation (in this example, this is the socket's executor).
+ return boost::asio::async_compose<
+ CompletionToken, void(boost::system::error_code)>(
+ async_write_messages_implementation{socket,
+ std::move(encoded_message), repeat_count,
+ std::move(delay_timer), boost::asio::coroutine()},
+ token, socket);
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_messages(socket, "Testing callback\r\n", 5,
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Messages sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_messages(
+ socket, "Testing future\r\n", 5, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Messages sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp11/socks4/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/socks4/Jamfile.v2
new file mode 100644
index 000000000..aa1492bad
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/socks4/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : sync_client.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/socks4/socks4.hpp b/src/boost/libs/asio/example/cpp11/socks4/socks4.hpp
new file mode 100644
index 000000000..e9d37fbb0
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/socks4/socks4.hpp
@@ -0,0 +1,143 @@
+//
+// socks4.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 SOCKS4_HPP
+#define SOCKS4_HPP
+
+#include <array>
+#include <string>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/ip/tcp.hpp>
+
+namespace socks4 {
+
+const unsigned char version = 0x04;
+
+class request
+{
+public:
+ enum command_type
+ {
+ connect = 0x01,
+ bind = 0x02
+ };
+
+ request(command_type cmd, const boost::asio::ip::tcp::endpoint& endpoint,
+ const std::string& user_id)
+ : version_(version),
+ command_(cmd),
+ user_id_(user_id),
+ null_byte_(0)
+ {
+ // Only IPv4 is supported by the SOCKS 4 protocol.
+ if (endpoint.protocol() != boost::asio::ip::tcp::v4())
+ {
+ throw boost::system::system_error(
+ boost::asio::error::address_family_not_supported);
+ }
+
+ // Convert port number to network byte order.
+ unsigned short port = endpoint.port();
+ port_high_byte_ = (port >> 8) & 0xff;
+ port_low_byte_ = port & 0xff;
+
+ // Save IP address in network byte order.
+ address_ = endpoint.address().to_v4().to_bytes();
+ }
+
+ std::array<boost::asio::const_buffer, 7> buffers() const
+ {
+ return
+ {
+ {
+ boost::asio::buffer(&version_, 1),
+ boost::asio::buffer(&command_, 1),
+ boost::asio::buffer(&port_high_byte_, 1),
+ boost::asio::buffer(&port_low_byte_, 1),
+ boost::asio::buffer(address_),
+ boost::asio::buffer(user_id_),
+ boost::asio::buffer(&null_byte_, 1)
+ }
+ };
+ }
+
+private:
+ unsigned char version_;
+ unsigned char command_;
+ unsigned char port_high_byte_;
+ unsigned char port_low_byte_;
+ boost::asio::ip::address_v4::bytes_type address_;
+ std::string user_id_;
+ unsigned char null_byte_;
+};
+
+class reply
+{
+public:
+ enum status_type
+ {
+ request_granted = 0x5a,
+ request_failed = 0x5b,
+ request_failed_no_identd = 0x5c,
+ request_failed_bad_user_id = 0x5d
+ };
+
+ reply()
+ : null_byte_(0),
+ status_()
+ {
+ }
+
+ std::array<boost::asio::mutable_buffer, 5> buffers()
+ {
+ return
+ {
+ {
+ boost::asio::buffer(&null_byte_, 1),
+ boost::asio::buffer(&status_, 1),
+ boost::asio::buffer(&port_high_byte_, 1),
+ boost::asio::buffer(&port_low_byte_, 1),
+ boost::asio::buffer(address_)
+ }
+ };
+ }
+
+ bool success() const
+ {
+ return null_byte_ == 0 && status_ == request_granted;
+ }
+
+ unsigned char status() const
+ {
+ return status_;
+ }
+
+ boost::asio::ip::tcp::endpoint endpoint() const
+ {
+ unsigned short port = port_high_byte_;
+ port = (port << 8) & 0xff00;
+ port = port | port_low_byte_;
+
+ boost::asio::ip::address_v4 address(address_);
+
+ return boost::asio::ip::tcp::endpoint(address, port);
+ }
+
+private:
+ unsigned char null_byte_;
+ unsigned char status_;
+ unsigned char port_high_byte_;
+ unsigned char port_low_byte_;
+ boost::asio::ip::address_v4::bytes_type address_;
+};
+
+} // namespace socks4
+
+#endif // SOCKS4_HPP
diff --git a/src/boost/libs/asio/example/cpp11/socks4/sync_client.cpp b/src/boost/libs/asio/example/cpp11/socks4/sync_client.cpp
new file mode 100644
index 000000000..1e8e6b713
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/socks4/sync_client.cpp
@@ -0,0 +1,93 @@
+//
+// sync_client.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <iomanip>
+#include <ostream>
+#include <string>
+#include <boost/asio.hpp>
+#include "socks4.hpp"
+
+using boost::asio::ip::tcp;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 4)
+ {
+ std::cout << "Usage: sync_client <socks4server> <socks4port> <user>\n";
+ std::cout << "Examples:\n";
+ std::cout << " sync_client 127.0.0.1 1080 chris\n";
+ std::cout << " sync_client localhost socks chris\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ // Get a list of endpoints corresponding to the SOCKS 4 server name.
+ tcp::resolver resolver(io_context);
+ auto endpoints = resolver.resolve(argv[1], argv[2]);
+
+ // Try each endpoint until we successfully establish a connection to the
+ // SOCKS 4 server.
+ tcp::socket socket(io_context);
+ boost::asio::connect(socket, endpoints);
+
+ // Get an endpoint for the Boost website. This will be passed to the SOCKS
+ // 4 server. Explicitly specify IPv4 since SOCKS 4 does not support IPv6.
+ auto http_endpoint = *resolver.resolve(tcp::v4(), "www.boost.org", "http");
+
+ // Send the request to the SOCKS 4 server.
+ socks4::request socks_request(
+ socks4::request::connect, http_endpoint, argv[3]);
+ boost::asio::write(socket, socks_request.buffers());
+
+ // Receive a response from the SOCKS 4 server.
+ socks4::reply socks_reply;
+ boost::asio::read(socket, socks_reply.buffers());
+
+ // Check whether we successfully negotiated with the SOCKS 4 server.
+ if (!socks_reply.success())
+ {
+ std::cout << "Connection failed.\n";
+ std::cout << "status = 0x" << std::hex << socks_reply.status();
+ return 1;
+ }
+
+ // Form the HTTP 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 response.
+ std::string request =
+ "GET / HTTP/1.0\r\n"
+ "Host: www.boost.org\r\n"
+ "Accept: */*\r\n"
+ "Connection: close\r\n\r\n";
+
+ // Send the HTTP request.
+ boost::asio::write(socket, boost::asio::buffer(request));
+
+ // Read until EOF, writing data to output as we go.
+ std::array<char, 512> response;
+ boost::system::error_code error;
+ while (std::size_t s = socket.read_some(
+ boost::asio::buffer(response), error))
+ std::cout.write(response.data(), s);
+ if (error != boost::asio::error::eof)
+ throw std::system_error(error);
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/spawn/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/spawn/Jamfile.v2
new file mode 100644
index 000000000..573fb124e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/spawn/Jamfile.v2
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe server
+ : echo_server.cpp
+ /boost/context//boost_context
+ /boost/coroutine//boost_coroutine
+ /boost/system//boost_system
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/spawn/echo_server.cpp b/src/boost/libs/asio/example/cpp11/spawn/echo_server.cpp
new file mode 100644
index 000000000..5fb6bbbfe
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/spawn/echo_server.cpp
@@ -0,0 +1,111 @@
+//
+// echo_server.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/spawn.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/write.hpp>
+#include <iostream>
+#include <memory>
+
+using boost::asio::ip::tcp;
+
+class session : public std::enable_shared_from_this<session>
+{
+public:
+ explicit session(boost::asio::io_context& io_context, tcp::socket socket)
+ : socket_(std::move(socket)),
+ timer_(io_context),
+ strand_(io_context.get_executor())
+ {
+ }
+
+ void go()
+ {
+ auto self(shared_from_this());
+ boost::asio::spawn(strand_,
+ [this, self](boost::asio::yield_context yield)
+ {
+ try
+ {
+ char data[128];
+ for (;;)
+ {
+ timer_.expires_from_now(std::chrono::seconds(10));
+ std::size_t n = socket_.async_read_some(boost::asio::buffer(data), yield);
+ boost::asio::async_write(socket_, boost::asio::buffer(data, n), yield);
+ }
+ }
+ catch (std::exception& e)
+ {
+ socket_.close();
+ timer_.cancel();
+ }
+ });
+
+ boost::asio::spawn(strand_,
+ [this, self](boost::asio::yield_context yield)
+ {
+ while (socket_.is_open())
+ {
+ boost::system::error_code ignored_ec;
+ timer_.async_wait(yield[ignored_ec]);
+ if (timer_.expires_from_now() <= std::chrono::seconds(0))
+ socket_.close();
+ }
+ });
+ }
+
+private:
+ tcp::socket socket_;
+ boost::asio::steady_timer timer_;
+ boost::asio::strand<boost::asio::io_context::executor_type> strand_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: echo_server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ boost::asio::spawn(io_context,
+ [&](boost::asio::yield_context yield)
+ {
+ tcp::acceptor acceptor(io_context,
+ tcp::endpoint(tcp::v4(), std::atoi(argv[1])));
+
+ for (;;)
+ {
+ boost::system::error_code ec;
+ tcp::socket socket(io_context);
+ acceptor.async_accept(socket, yield[ec]);
+ if (!ec)
+ {
+ std::make_shared<session>(io_context, std::move(socket))->go();
+ }
+ }
+ });
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/spawn/parallel_grep.cpp b/src/boost/libs/asio/example/cpp11/spawn/parallel_grep.cpp
new file mode 100644
index 000000000..2c17131a5
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/spawn/parallel_grep.cpp
@@ -0,0 +1,84 @@
+//
+// parallel_grep.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/dispatch.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/spawn.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+using boost::asio::dispatch;
+using boost::asio::spawn;
+using boost::asio::strand;
+using boost::asio::thread_pool;
+using boost::asio::yield_context;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc < 2)
+ {
+ std::cerr << "Usage: parallel_grep <string> <files...>\n";
+ return 1;
+ }
+
+ // We use a fixed size pool of threads for reading the input files. The
+ // number of threads is automatically determined based on the number of
+ // CPUs available in the system.
+ thread_pool pool;
+
+ // To prevent the output from being garbled, we use a strand to synchronise
+ // printing.
+ strand<thread_pool::executor_type> output_strand(pool.get_executor());
+
+ // Spawn a new coroutine for each file specified on the command line.
+ std::string search_string = argv[1];
+ for (int argn = 2; argn < argc; ++argn)
+ {
+ std::string input_file = argv[argn];
+ spawn(pool,
+ [=](yield_context yield)
+ {
+ std::ifstream is(input_file.c_str());
+ std::string line;
+ std::size_t line_num = 0;
+ while (std::getline(is, line))
+ {
+ // If we find a match, send a message to the output.
+ if (line.find(search_string) != std::string::npos)
+ {
+ dispatch(output_strand,
+ [=]
+ {
+ std::cout << input_file << ':' << line << std::endl;
+ });
+ }
+
+ // Every so often we yield control to another coroutine.
+ if (++line_num % 10 == 0)
+ post(yield);
+ }
+ });
+ }
+
+ // Join the thread pool to wait for all the spawned tasks to complete.
+ pool.join();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/ssl/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/ssl/Jamfile.v2
new file mode 100644
index 000000000..a7805abb8
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/ssl/Jamfile.v2
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+import os ;
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+if [ os.name ] = NT
+{
+ lib ssl : : <name>ssleay32 ;
+ lib crypto : : <name>libeay32 ;
+}
+else
+{
+ lib ssl ;
+ lib crypto ;
+}
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ <library>ssl
+ <library>crypto
+ ;
+
+exe client : client.cpp ;
+exe server : server.cpp ;
diff --git a/src/boost/libs/asio/example/cpp11/ssl/README b/src/boost/libs/asio/example/cpp11/ssl/README
new file mode 100644
index 000000000..7dea8cc9b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/ssl/README
@@ -0,0 +1,8 @@
+The passphrase for both the CA and server private keys is "test".
+
+
+-------------------------------------------------------------------------------
+Copyright (c) 2003-2020 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/src/boost/libs/asio/example/cpp11/ssl/ca.pem b/src/boost/libs/asio/example/cpp11/ssl/ca.pem
new file mode 100644
index 000000000..1ee5f2ca4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/ssl/ca.pem
@@ -0,0 +1,49 @@
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIJAMJYU3U6A0IRMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
+BAYTAkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChME
+YXNpbzAeFw0xNTExMTgyMjMzNDhaFw0yMDExMTYyMjMzNDhaMDsxCzAJBgNVBAYT
+AkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChMEYXNp
+bzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcRJocHdVMdLUJ/pypY
+QVSTC0t3IIgjwjazrK3kAaoIMvzPmDFxEXWcDx+nyz8kQ/E38Ir/ef2BCNGci5hu
+wkfMSuMoW9l2N4hx3QCcF46tTDEZztFxWAH7QbE2wYMlMgKZSxWimNfq0YjxEEXb
+QM0lGPLFh7Xoko29H0F3LKaaQV9u/vop3Hs0h12HeWlY4PiLp7QQTNGqbWcXycA0
+NZ/fyismireyEvPAgo6L8iXuAi7g0TVKVNlrticGGjMcMq6IMvxzEpSMkuMQ5rWj
+pZjWOoBjSYBuXdblcBRvXhOr2Ws8jJLMZfehKq9q1reQfoGV6xMnbwmumSXbWRWT
+0vkCAwEAAaOBnTCBmjAdBgNVHQ4EFgQUK/Zv/AVtfIeucJw8VEtux1dhI1YwawYD
+VR0jBGQwYoAUK/Zv/AVtfIeucJw8VEtux1dhI1ahP6Q9MDsxCzAJBgNVBAYTAkFV
+MQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChMEYXNpb4IJ
+AMJYU3U6A0IRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABLYXimq
+v/HLyIJi7Xn8AJUsICj8LKF/J24nwwiF+ibf7UkoChJURs4nN78bod/lpDVPTEVl
+gTBdV/vBJs416sCEFfsGjqB9OBYj4gb0VaJDsQd0+NMvXp0faKv2y9wgScxG9/cg
+aM7eRmyfMn1qjb6tpNxVOPpe/nFi8Vx/1orejBRaZr4zF5TkoPepfwLWQeXDUIdE
++QHZ60jZAkR5RXTVU4u3kOKcJs839pmJYyxM4H2VxpR18vy4/YdIVWkREIUM2OgT
+5iznIQIIgR56QRGP85uef+I6n0BHzrBk6du69bkQFxrFjLVGlal4bIQqSg4KGWgx
+dEdymMWzmMxpO9s=
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEAxxEmhwd1Ux0tQn+nKlhBVJMLS3cgiCPCNrOsreQBqggy/M+Y
+MXERdZwPH6fLPyRD8Tfwiv95/YEI0ZyLmG7CR8xK4yhb2XY3iHHdAJwXjq1MMRnO
+0XFYAftBsTbBgyUyAplLFaKY1+rRiPEQRdtAzSUY8sWHteiSjb0fQXcspppBX27+
++incezSHXYd5aVjg+IuntBBM0aptZxfJwDQ1n9/KKyaKt7IS88CCjovyJe4CLuDR
+NUpU2Wu2JwYaMxwyrogy/HMSlIyS4xDmtaOlmNY6gGNJgG5d1uVwFG9eE6vZazyM
+ksxl96Eqr2rWt5B+gZXrEydvCa6ZJdtZFZPS+QIDAQABAoIBAQCOma+SvPoDzvvU
+DiPOxqgOEMPfjHfGbm86xl0luBalGfiEd6WbjVanfGKtF4MWOUFec+chez+FJMEP
+fufVC0qrKiJfNVMOpYvEd2SMgkSx1VymM8me6WXVDYsSipn2+1cm228ZEYAR9Emj
+oqQ4loaGLlP/3RaJbhBF7ruMJvXaZZQ4fZy74Z4tyRaaE1B659ua7Rjne7eNhQE8
+cR7cQDkxsNNN3LTbfLRwEc/gcDXWgLe5JlR/K4ZrdKc3lyivm+Uew3ubKs+fgkyY
+kHmuI3RJGIjpnsZW0/So+pHm3b/fo6lmlhTXtNNd+tkkKn2K9ttbXT3Sc13Pc+4w
+c4MLyUpdAoGBAOxTtGDpeF6U4s+GPuOCzHCwKQyzfOyCL/UTZv1UJX7Kn1FYycJH
+eOjtBRtS661cGkGd1MPfjdX2VV84AmBGDUmRqJ2KfTI1NjLAEJ115ANTpmSTm3lF
+UYncgbzl6aflLpjE1mgY+JTJykYeN5jhhO0r2bsdY7S+zaMCSI5NLuznAoGBANej
+aMtqLg2qKoq+fUkNBHHLXelR5dBXFnKgSrTj++H4yeW9pYbl8bK3gTF3I5+dSjHW
+DdC4+X09iPqY7p8vm8Gq/vgO8Bu+EnKNVr80PJSj7AzFGd6mk/CVrAzoY2XJWbAp
+YFwpo1WfHjS5wBfQzBlXY7kWVB7fj32kk14PYmUfAoGBAJXfd7NGHPoOfdCSGGv8
+VV7ZuQ6+/WiYH4XS6iuaI7VHFsZmAn3dCcbeGbD8Y04r7NLUH0yhB7g7YmTihk87
+3c1cPIy8eS1QJbEFsQPK8fFSKWH7YkwEM/O0DesX+5hodaaYnkiiHXNujYLuQuAH
+lV87wfcyajsEDjFkj1L/i9TdAoGBAKYfRUQv8HqmdU+doHb+iEYCHb75UMpHzQtR
+YTwpxoo3V5Kdnz9lNeYwaF7rIY59ZgMunEYHumw5U6V625nW228/hF0lZOR6cUu+
+hu2WGHWKMvdDgMJ+IcpeA8WN4cUwcN+9gHZ/vUzg4CxOTSYLvLBpGnIkOXnvUGPC
+vaTgxTSRAoGBAOHcuZ9hcUrPuVI1HVkjQQLu5mLZ3tz6linEbe/RCdJMK8JrRX4w
+ubB7gFclMYGbLlDNAJVYkydJaCy/2NAI3rfsOda+VmDqGx6z4BbSGceHhomyU1Oo
+1H7YaXsuzDkzl23HRsyp0pKJpTdghZdbVsGF8vAB8ygK3ehM233neSln
+-----END RSA PRIVATE KEY-----
diff --git a/src/boost/libs/asio/example/cpp11/ssl/client.cpp b/src/boost/libs/asio/example/cpp11/ssl/client.cpp
new file mode 100644
index 000000000..175c85156
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/ssl/client.cpp
@@ -0,0 +1,165 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
+
+using boost::asio::ip::tcp;
+using std::placeholders::_1;
+using std::placeholders::_2;
+
+enum { max_length = 1024 };
+
+class client
+{
+public:
+ client(boost::asio::io_context& io_context,
+ boost::asio::ssl::context& context,
+ const tcp::resolver::results_type& endpoints)
+ : socket_(io_context, context)
+ {
+ socket_.set_verify_mode(boost::asio::ssl::verify_peer);
+ socket_.set_verify_callback(
+ std::bind(&client::verify_certificate, this, _1, _2));
+
+ connect(endpoints);
+ }
+
+private:
+ bool verify_certificate(bool preverified,
+ boost::asio::ssl::verify_context& ctx)
+ {
+ // The verify callback can be used to check whether the certificate that is
+ // being presented is valid for the peer. For example, RFC 2818 describes
+ // the steps involved in doing this for HTTPS. Consult the OpenSSL
+ // documentation for more details. Note that the callback is called once
+ // for each certificate in the certificate chain, starting from the root
+ // certificate authority.
+
+ // In this example we will simply print the certificate's subject name.
+ char subject_name[256];
+ X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
+ X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
+ std::cout << "Verifying " << subject_name << "\n";
+
+ return preverified;
+ }
+
+ void connect(const tcp::resolver::results_type& endpoints)
+ {
+ boost::asio::async_connect(socket_.lowest_layer(), endpoints,
+ [this](const boost::system::error_code& error,
+ const tcp::endpoint& /*endpoint*/)
+ {
+ if (!error)
+ {
+ handshake();
+ }
+ else
+ {
+ std::cout << "Connect failed: " << error.message() << "\n";
+ }
+ });
+ }
+
+ void handshake()
+ {
+ socket_.async_handshake(boost::asio::ssl::stream_base::client,
+ [this](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ send_request();
+ }
+ else
+ {
+ std::cout << "Handshake failed: " << error.message() << "\n";
+ }
+ });
+ }
+
+ void send_request()
+ {
+ std::cout << "Enter message: ";
+ std::cin.getline(request_, max_length);
+ size_t request_length = std::strlen(request_);
+
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(request_, request_length),
+ [this](const boost::system::error_code& error, std::size_t length)
+ {
+ if (!error)
+ {
+ receive_response(length);
+ }
+ else
+ {
+ std::cout << "Write failed: " << error.message() << "\n";
+ }
+ });
+ }
+
+ void receive_response(std::size_t length)
+ {
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(reply_, length),
+ [this](const boost::system::error_code& error, std::size_t length)
+ {
+ if (!error)
+ {
+ std::cout << "Reply: ";
+ std::cout.write(reply_, length);
+ std::cout << "\n";
+ }
+ else
+ {
+ std::cout << "Read failed: " << error.message() << "\n";
+ }
+ });
+ }
+
+ boost::asio::ssl::stream<tcp::socket> socket_;
+ char request_[max_length];
+ char reply_[max_length];
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ tcp::resolver resolver(io_context);
+ auto endpoints = resolver.resolve(argv[1], argv[2]);
+
+ boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
+ ctx.load_verify_file("ca.pem");
+
+ client c(io_context, ctx, endpoints);
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/ssl/dh2048.pem b/src/boost/libs/asio/example/cpp11/ssl/dh2048.pem
new file mode 100644
index 000000000..07250cca6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/ssl/dh2048.pem
@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEAyNnxZSYc6J89mDNnqOH8bnwBiAJxcaUS3PkIEcwW8D9o2BlNq6EO
+XKMIbdfwPFZi80GMpNu3YP2A2B42sAHmb7w7ZA92QDv3JjqzR0QuS/CkMv4CEjha
+QBFwBDDWnnHBSj4w/t54ii0SH34mWcjBItI2eMtnM9J6fnvNiWqJxdt4iA4mZjZD
+qZTjIRyjgKAevzkqAlBqQRoVUUgu+9Cf29wXjVl3bE+0VU5CdFeyT+Y9yunz88mq
+rGyx1uPt+zbIfxuNLH+coY67y1ht7iZEL5WLd3wGCycRT+lYy2AL/rxGBPxStFIT
+2bOkQao6sAfb4UdGEUlwHUXZrAV51oM30wIBAg==
+-----END DH PARAMETERS-----
diff --git a/src/boost/libs/asio/example/cpp11/ssl/server.cpp b/src/boost/libs/asio/example/cpp11/ssl/server.cpp
new file mode 100644
index 000000000..32936a674
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/ssl/server.cpp
@@ -0,0 +1,143 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <functional>
+#include <iostream>
+#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
+
+using boost::asio::ip::tcp;
+
+class session : public std::enable_shared_from_this<session>
+{
+public:
+ session(tcp::socket socket, boost::asio::ssl::context& context)
+ : socket_(std::move(socket), context)
+ {
+ }
+
+ void start()
+ {
+ do_handshake();
+ }
+
+private:
+ void do_handshake()
+ {
+ auto self(shared_from_this());
+ socket_.async_handshake(boost::asio::ssl::stream_base::server,
+ [this, self](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ do_read();
+ }
+ });
+ }
+
+ void do_read()
+ {
+ auto self(shared_from_this());
+ socket_.async_read_some(boost::asio::buffer(data_),
+ [this, self](const boost::system::error_code& ec, std::size_t length)
+ {
+ if (!ec)
+ {
+ do_write(length);
+ }
+ });
+ }
+
+ void do_write(std::size_t length)
+ {
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
+ [this, self](const boost::system::error_code& ec,
+ std::size_t /*length*/)
+ {
+ if (!ec)
+ {
+ do_read();
+ }
+ });
+ }
+
+ boost::asio::ssl::stream<tcp::socket> socket_;
+ char data_[1024];
+};
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context, unsigned short port)
+ : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
+ context_(boost::asio::ssl::context::sslv23)
+ {
+ context_.set_options(
+ boost::asio::ssl::context::default_workarounds
+ | boost::asio::ssl::context::no_sslv2
+ | boost::asio::ssl::context::single_dh_use);
+ context_.set_password_callback(std::bind(&server::get_password, this));
+ context_.use_certificate_chain_file("server.pem");
+ context_.use_private_key_file("server.pem", boost::asio::ssl::context::pem);
+ context_.use_tmp_dh_file("dh2048.pem");
+
+ do_accept();
+ }
+
+private:
+ std::string get_password() const
+ {
+ return "test";
+ }
+
+ void do_accept()
+ {
+ acceptor_.async_accept(
+ [this](const boost::system::error_code& error, tcp::socket socket)
+ {
+ if (!error)
+ {
+ std::make_shared<session>(std::move(socket), context_)->start();
+ }
+
+ do_accept();
+ });
+ }
+
+ tcp::acceptor acceptor_;
+ boost::asio::ssl::context context_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: server <port>\n";
+ return 1;
+ }
+
+ boost::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() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/ssl/server.pem b/src/boost/libs/asio/example/cpp11/ssl/server.pem
new file mode 100644
index 000000000..37ea6e267
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/ssl/server.pem
@@ -0,0 +1,71 @@
+-----BEGIN CERTIFICATE-----
+MIIDAzCCAesCCQD9QcRiWk0y9TANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJB
+VTEMMAoGA1UECBMDTlNXMQ8wDQYDVQQHEwZTeWRuZXkxDTALBgNVBAoTBGFzaW8w
+HhcNMTUxMTE4MjIzNzMxWhcNMjAxMTE2MjIzNzMxWjBMMQswCQYDVQQGEwJBVTEM
+MAoGA1UECBMDTlNXMQ8wDQYDVQQHEwZTeWRuZXkxDTALBgNVBAoTBGFzaW8xDzAN
+BgNVBAsTBnNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALr0
++NXSklsGJR7HYHP/H4V5+KpYrmFKva/K7iiqi+XyWEjGnj+/iImJW26phhg9GouN
+JJxdrP7/0LwpMsEC/9v09dMNAEewtYhPgD4kiUH/E/79wVmayMZZZGrpF9Rw+wWv
+q58y3L1wKge3qilX6slVDdNhqU3vBiMKEJfsjE4PKcEVjPCjVJG2562eHK9FxyjQ
+DykyH61lQKBQOiElilPQKzAO7U36yTvs+chWuUfK47B8EC+PJ5KcLEppli4ljlwE
+w01HnGxwvjDLobKm2jL6CWi3aYGWudyTsNAd7YC5C7psktBypQLBcfp7uUrrR5Bb
+PEjFHJUWIlyoYvm2OjMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAtceVW6tixFsB
+ZRhjL5aRCcbx2iMwEXd54lcP6BWe1qOcDPHoSYI1zvvGzohbEvBfqUv78S9MtzaT
+gMe5rIU9M1ZM09PyaM6ZutGpKHE8L4qcOslTt41GQFsSqPFdcbgSV20MvBzjGayR
+AI/WV0avW3oasdetJPZCR7bRbCbMbWTgclUfv5F25ENcR+BhNuilfL15owL0s4sS
+Wb4jOOHhXV9iXeS2dH0snFqv4BmQ9ZoA7zbM9lG3EU5DuxHESYkCnzJyEqqY3vWv
+PFRViCxLp5LQLmkTQ3dglVQA4x6ZaonaewdPtdhjkLUuIqDvQx5+kIaOELbSws+c
+bREYlnGrFw==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,D459676347D389E9135496D8AAFA7953
+
+wbrjxr9NHur8kgxDsgXOY9qFGKpONIQLxkuahUrDD/H+s/l7ugsLWOPsOXbjNL/7
+QYUBAx85HKm9D8BQ5g78Y82qfArap3/3IIuysDfQDh4fQodhVtmGTFiCOvudlGEp
+lq1niQRLThlxeRoFphH8KKiOTO9a/d8tdL7zRmiFwnVnhK4014mgVmgcSefA1AF5
+RbJAeMclUKddG6ltQK00ptg84CDXiMWQXFBGGmQ1av2lyFzC+xLP+qDqZAYTM9lZ
+NFRo2oEZP1ozfOVNSbXTanJgZ0DSSmhGE1PcVrHSeE/v+k1kPh3oVKi9GV51kIDC
+Zd9f/XltuDOzy1Ybn6gRy4nzNpzcwjSCIHEdSD5nxU5JfHfQ3OtnsEab7qf989iP
+s2LbCSp5uGTMvfesMIkixIZAQp2FeahZTAgU2Vx+wi5Kks68rOqeywEfzACL/Um5
+7XZu8gDs4MgRRWnxK1BbJDPifICLvSJZvgB9FKX/hk4FHFF+MtcrkalehCuLooDV
+3rfHNvRSbg7J97XQ3QC+k9ZDaumpy6n+LhaVv7BIJRBnBBtZ5Eg3DmPg6flqaHAU
+Y/8d82wb/pCmbvR3B1/Ebgs84DPJ+uZnY9M5Iwx19oqlVSR2ts/Tx619LGAm+BiQ
+7YDoC4CFmpAA8Uw0xnUbNgx94NdNmlnLeLtS50b0XlWpHKbVzmVbNYEjY6NHMlLt
+aqxWHTYTa7g/c1bg2/nxF1Lbfu5VSTROGBUuer1c3yzVuyBrjcX92Jp4BJH78qOp
+N6lY6MnH4HYRXHjzlt/S0ZzO0faPPe18Q8SWvnDVuE3fYzzL772B56d2t8eodc+/
+t6M3qJ60eXdsmgYOaPRLRUovN2xT2UUr0+biuguHyqfaVfcEU/adw+b9oUVE+5Nw
+nZHI5qhPnhLxChyZqbBl68zMUyKlfff4OyLvRGpfcHwBw6DTGjduB+DDsqqkcIB9
+2VL6nps7ZVCwMPI18siUd6cttEOf6ZXrVqHg9wfDvJOlh2NNKNLxSAFubHc90Jlj
+KejrWenXo2w6YkSUeTV4t4cWu7U8rXIkTJXDl1S6NO8DWqNDo5KjgJ2SK5NlSOJ7
+jgECn390ooneJOxxytPVQO2xppXQZZS65RHrvhB+ss5xUknly9q+ICyt6xTR9nqA
+PKkeSE6qVY0J4JgFXpkgQxgwMnjSED3LKr3jlz28pr5cC6tsc5SSlekHjT2fcSrX
+uccaVahaJRigf+q+4XzmJtdwbZU+YWGZRVMlQLA5yzPHQHDYkPpOeYU4WReND8S4
+TZRkPHaxOZ2lKQwJB93V8Vbt2MvwRy392452a33S4TcQLaWzoOljXjmZjrp2rvRz
+prBaNe8LnO4V8Oliv+H+E0UWiWFDuI+HBy4X4O9plsbw/gk64Phl9qLiBwaX/AIR
+66FXvC/czABo9oSt2jekcMtJofYr8Gr2bsJlt5ZX+GEOxz4jMv7xvz5/L3W7jVav
+pHGIv4xfN9FrXzL47O7UuUF9xZg4Rp/fxwpgEDNZmX/3DnP0ewZQUcgUX0pdqNGQ
+YVqJXcRF7KqG2NSQFuwPESZQnxU0WzSgRyUae7xg1WKfSuN8NVAzKhOgeqlD2IAo
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIJAMJYU3U6A0IRMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
+BAYTAkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChME
+YXNpbzAeFw0xNTExMTgyMjMzNDhaFw0yMDExMTYyMjMzNDhaMDsxCzAJBgNVBAYT
+AkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChMEYXNp
+bzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcRJocHdVMdLUJ/pypY
+QVSTC0t3IIgjwjazrK3kAaoIMvzPmDFxEXWcDx+nyz8kQ/E38Ir/ef2BCNGci5hu
+wkfMSuMoW9l2N4hx3QCcF46tTDEZztFxWAH7QbE2wYMlMgKZSxWimNfq0YjxEEXb
+QM0lGPLFh7Xoko29H0F3LKaaQV9u/vop3Hs0h12HeWlY4PiLp7QQTNGqbWcXycA0
+NZ/fyismireyEvPAgo6L8iXuAi7g0TVKVNlrticGGjMcMq6IMvxzEpSMkuMQ5rWj
+pZjWOoBjSYBuXdblcBRvXhOr2Ws8jJLMZfehKq9q1reQfoGV6xMnbwmumSXbWRWT
+0vkCAwEAAaOBnTCBmjAdBgNVHQ4EFgQUK/Zv/AVtfIeucJw8VEtux1dhI1YwawYD
+VR0jBGQwYoAUK/Zv/AVtfIeucJw8VEtux1dhI1ahP6Q9MDsxCzAJBgNVBAYTAkFV
+MQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTENMAsGA1UEChMEYXNpb4IJ
+AMJYU3U6A0IRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABLYXimq
+v/HLyIJi7Xn8AJUsICj8LKF/J24nwwiF+ibf7UkoChJURs4nN78bod/lpDVPTEVl
+gTBdV/vBJs416sCEFfsGjqB9OBYj4gb0VaJDsQd0+NMvXp0faKv2y9wgScxG9/cg
+aM7eRmyfMn1qjb6tpNxVOPpe/nFi8Vx/1orejBRaZr4zF5TkoPepfwLWQeXDUIdE
++QHZ60jZAkR5RXTVU4u3kOKcJs839pmJYyxM4H2VxpR18vy4/YdIVWkREIUM2OgT
+5iznIQIIgR56QRGP85uef+I6n0BHzrBk6du69bkQFxrFjLVGlal4bIQqSg4KGWgx
+dEdymMWzmMxpO9s=
+-----END CERTIFICATE-----
diff --git a/src/boost/libs/asio/example/cpp11/timeouts/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/timeouts/Jamfile.v2
new file mode 100644
index 000000000..dcc83c435
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/timeouts/Jamfile.v2
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe async_tcp_client : async_tcp_client.cpp ;
+exe blocking_tcp_client : blocking_tcp_client.cpp ;
+exe blocking_token_tcp_client : blocking_token_tcp_client.cpp ;
+exe blocking_udp_client : blocking_udp_client.cpp ;
+exe server : server.cpp ;
diff --git a/src/boost/libs/asio/example/cpp11/timeouts/async_tcp_client.cpp b/src/boost/libs/asio/example/cpp11/timeouts/async_tcp_client.cpp
new file mode 100644
index 000000000..9c6719060
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/timeouts/async_tcp_client.cpp
@@ -0,0 +1,311 @@
+//
+// async_tcp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <string>
+
+using boost::asio::steady_timer;
+using boost::asio::ip::tcp;
+using std::placeholders::_1;
+using std::placeholders::_2;
+
+//
+// This class manages socket timeouts by applying the concept of a deadline.
+// Some asynchronous operations are given deadlines by which they must complete.
+// Deadlines are enforced by an "actor" that persists for the lifetime of the
+// client object:
+//
+// +----------------+
+// | |
+// | check_deadline |<---+
+// | | |
+// +----------------+ | async_wait()
+// | |
+// +---------+
+//
+// If the deadline actor determines that the deadline has expired, the socket
+// is closed and any outstanding operations are consequently cancelled.
+//
+// Connection establishment involves trying each endpoint in turn until a
+// connection is successful, or the available endpoints are exhausted. If the
+// deadline actor closes the socket, the connect actor is woken up and moves to
+// the next endpoint.
+//
+// +---------------+
+// | |
+// | start_connect |<---+
+// | | |
+// +---------------+ |
+// | |
+// async_- | +----------------+
+// connect() | | |
+// +--->| handle_connect |
+// | |
+// +----------------+
+// :
+// Once a connection is :
+// made, the connect :
+// actor forks in two - :
+// :
+// an actor for reading : and an actor for
+// inbound messages: : sending heartbeats:
+// :
+// +------------+ : +-------------+
+// | |<- - - - -+- - - - ->| |
+// | start_read | | start_write |<---+
+// | |<---+ | | |
+// +------------+ | +-------------+ | async_wait()
+// | | | |
+// async_- | +-------------+ async_- | +--------------+
+// read_- | | | write() | | |
+// until() +--->| handle_read | +--->| handle_write |
+// | | | |
+// +-------------+ +--------------+
+//
+// The input actor reads messages from the socket, where messages are delimited
+// by the newline character. The deadline for a complete message is 30 seconds.
+//
+// The heartbeat actor sends a heartbeat (a message that consists of a single
+// newline character) every 10 seconds. In this example, no deadline is applied
+// to message sending.
+//
+class client
+{
+public:
+ client(boost::asio::io_context& io_context)
+ : socket_(io_context),
+ deadline_(io_context),
+ heartbeat_timer_(io_context)
+ {
+ }
+
+ // Called by the user of the client class to initiate the connection process.
+ // The endpoints will have been obtained using a tcp::resolver.
+ void start(tcp::resolver::results_type endpoints)
+ {
+ // Start the connect actor.
+ endpoints_ = endpoints;
+ start_connect(endpoints_.begin());
+
+ // Start the deadline actor. You will note that we're not setting any
+ // particular deadline here. Instead, the connect and input actors will
+ // update the deadline prior to each asynchronous operation.
+ deadline_.async_wait(std::bind(&client::check_deadline, this));
+ }
+
+ // This function terminates all the actors to shut down the connection. It
+ // may be called by the user of the client class, or by the class itself in
+ // response to graceful termination or an unrecoverable error.
+ void stop()
+ {
+ stopped_ = true;
+ boost::system::error_code ignored_error;
+ socket_.close(ignored_error);
+ deadline_.cancel();
+ heartbeat_timer_.cancel();
+ }
+
+private:
+ void start_connect(tcp::resolver::results_type::iterator endpoint_iter)
+ {
+ if (endpoint_iter != endpoints_.end())
+ {
+ std::cout << "Trying " << endpoint_iter->endpoint() << "...\n";
+
+ // Set a deadline for the connect operation.
+ deadline_.expires_after(std::chrono::seconds(60));
+
+ // Start the asynchronous connect operation.
+ socket_.async_connect(endpoint_iter->endpoint(),
+ std::bind(&client::handle_connect,
+ this, _1, endpoint_iter));
+ }
+ else
+ {
+ // There are no more endpoints to try. Shut down the client.
+ stop();
+ }
+ }
+
+ void handle_connect(const boost::system::error_code& error,
+ tcp::resolver::results_type::iterator endpoint_iter)
+ {
+ if (stopped_)
+ return;
+
+ // The async_connect() function automatically opens the socket at the start
+ // of the asynchronous operation. If the socket is closed at this time then
+ // the timeout handler must have run first.
+ if (!socket_.is_open())
+ {
+ std::cout << "Connect timed out\n";
+
+ // Try the next available endpoint.
+ start_connect(++endpoint_iter);
+ }
+
+ // Check if the connect operation failed before the deadline expired.
+ else if (error)
+ {
+ std::cout << "Connect error: " << error.message() << "\n";
+
+ // We need to close the socket used in the previous connection attempt
+ // before starting a new one.
+ socket_.close();
+
+ // Try the next available endpoint.
+ start_connect(++endpoint_iter);
+ }
+
+ // Otherwise we have successfully established a connection.
+ else
+ {
+ std::cout << "Connected to " << endpoint_iter->endpoint() << "\n";
+
+ // Start the input actor.
+ start_read();
+
+ // Start the heartbeat actor.
+ start_write();
+ }
+ }
+
+ void start_read()
+ {
+ // Set a deadline for the read operation.
+ deadline_.expires_after(std::chrono::seconds(30));
+
+ // Start an asynchronous operation to read a newline-delimited message.
+ boost::asio::async_read_until(socket_,
+ boost::asio::dynamic_buffer(input_buffer_), '\n',
+ std::bind(&client::handle_read, this, _1, _2));
+ }
+
+ void handle_read(const boost::system::error_code& error, std::size_t n)
+ {
+ if (stopped_)
+ return;
+
+ if (!error)
+ {
+ // Extract the newline-delimited message from the buffer.
+ std::string line(input_buffer_.substr(0, n - 1));
+ input_buffer_.erase(0, n);
+
+ // Empty messages are heartbeats and so ignored.
+ if (!line.empty())
+ {
+ std::cout << "Received: " << line << "\n";
+ }
+
+ start_read();
+ }
+ else
+ {
+ std::cout << "Error on receive: " << error.message() << "\n";
+
+ stop();
+ }
+ }
+
+ void start_write()
+ {
+ if (stopped_)
+ return;
+
+ // Start an asynchronous operation to send a heartbeat message.
+ boost::asio::async_write(socket_, boost::asio::buffer("\n", 1),
+ std::bind(&client::handle_write, this, _1));
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (stopped_)
+ return;
+
+ if (!error)
+ {
+ // Wait 10 seconds before sending the next heartbeat.
+ heartbeat_timer_.expires_after(std::chrono::seconds(10));
+ heartbeat_timer_.async_wait(std::bind(&client::start_write, this));
+ }
+ else
+ {
+ std::cout << "Error on heartbeat: " << error.message() << "\n";
+
+ stop();
+ }
+ }
+
+ void check_deadline()
+ {
+ if (stopped_)
+ return;
+
+ // Check whether the deadline has passed. We compare the deadline against
+ // the current time since a new asynchronous operation may have moved the
+ // deadline before this actor had a chance to run.
+ if (deadline_.expiry() <= steady_timer::clock_type::now())
+ {
+ // The deadline has passed. The socket is closed so that any outstanding
+ // asynchronous operations are cancelled.
+ socket_.close();
+
+ // There is no longer an active deadline. The expiry is set to the
+ // maximum time point so that the actor takes no action until a new
+ // deadline is set.
+ deadline_.expires_at(steady_timer::time_point::max());
+ }
+
+ // Put the actor back to sleep.
+ deadline_.async_wait(std::bind(&client::check_deadline, this));
+ }
+
+private:
+ bool stopped_ = false;
+ tcp::resolver::results_type endpoints_;
+ tcp::socket socket_;
+ std::string input_buffer_;
+ steady_timer deadline_;
+ steady_timer heartbeat_timer_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+ tcp::resolver r(io_context);
+ client c(io_context);
+
+ c.start(r.resolve(argv[1], argv[2]));
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/timeouts/blocking_tcp_client.cpp b/src/boost/libs/asio/example/cpp11/timeouts/blocking_tcp_client.cpp
new file mode 100644
index 000000000..f64ba66a2
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/timeouts/blocking_tcp_client.cpp
@@ -0,0 +1,192 @@
+//
+// blocking_tcp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/buffer.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+using boost::asio::ip::tcp;
+
+//----------------------------------------------------------------------
+
+//
+// This class manages socket timeouts by running the io_context using the timed
+// io_context::run_for() member function. Each asynchronous operation is given
+// a timeout within which it must complete. The socket operations themselves
+// use lambdas as completion handlers. For a given socket operation, the client
+// object runs the io_context to block thread execution until the operation
+// completes or the timeout is reached. If the io_context::run_for() function
+// times out, the socket is closed and the outstanding asynchronous operation
+// is cancelled.
+//
+class client
+{
+public:
+ void connect(const std::string& host, const std::string& service,
+ std::chrono::steady_clock::duration timeout)
+ {
+ // Resolve the host name and service to a list of endpoints.
+ auto endpoints = tcp::resolver(io_context_).resolve(host, service);
+
+ // Start the asynchronous operation itself. The lambda that is used as a
+ // callback will update the error variable when the operation completes.
+ // The blocking_udp_client.cpp example shows how you can use std::bind
+ // rather than a lambda.
+ boost::system::error_code error;
+ boost::asio::async_connect(socket_, endpoints,
+ [&](const boost::system::error_code& result_error,
+ const tcp::endpoint& /*result_endpoint*/)
+ {
+ error = result_error;
+ });
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether a connection was successfully established.
+ if (error)
+ throw std::system_error(error);
+ }
+
+ std::string read_line(std::chrono::steady_clock::duration timeout)
+ {
+ // Start the asynchronous operation. The lambda that is used as a callback
+ // will update the error and n variables when the operation completes. The
+ // blocking_udp_client.cpp example shows how you can use std::bind rather
+ // than a lambda.
+ boost::system::error_code error;
+ std::size_t n = 0;
+ boost::asio::async_read_until(socket_,
+ boost::asio::dynamic_buffer(input_buffer_), '\n',
+ [&](const boost::system::error_code& result_error,
+ std::size_t result_n)
+ {
+ error = result_error;
+ n = result_n;
+ });
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether the read completed successfully.
+ if (error)
+ throw std::system_error(error);
+
+ std::string line(input_buffer_.substr(0, n - 1));
+ input_buffer_.erase(0, n);
+ return line;
+ }
+
+ void write_line(const std::string& line,
+ std::chrono::steady_clock::duration timeout)
+ {
+ std::string data = line + "\n";
+
+ // Start the asynchronous operation itself. The lambda that is used as a
+ // callback will update the error variable when the operation completes.
+ // The blocking_udp_client.cpp example shows how you can use std::bind
+ // rather than a lambda.
+ boost::system::error_code error;
+ boost::asio::async_write(socket_, boost::asio::buffer(data),
+ [&](const boost::system::error_code& result_error,
+ std::size_t /*result_n*/)
+ {
+ error = result_error;
+ });
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether the read completed successfully.
+ if (error)
+ throw std::system_error(error);
+ }
+
+private:
+ void run(std::chrono::steady_clock::duration timeout)
+ {
+ // Restart the io_context, as it may have been left in the "stopped" state
+ // by a previous operation.
+ io_context_.restart();
+
+ // Block until the asynchronous operation has completed, or timed out. If
+ // 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);
+
+ // If the asynchronous operation completed successfully then the io_context
+ // would have been stopped due to running out of work. If it was not
+ // stopped, then the io_context::run_for call must have timed out.
+ if (!io_context_.stopped())
+ {
+ // Close the socket to cancel the outstanding asynchronous operation.
+ socket_.close();
+
+ // Run the io_context again until the operation completes.
+ io_context_.run();
+ }
+ }
+
+ boost::asio::io_context io_context_;
+ tcp::socket socket_{io_context_};
+ std::string input_buffer_;
+};
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 4)
+ {
+ std::cerr << "Usage: blocking_tcp_client <host> <port> <message>\n";
+ return 1;
+ }
+
+ client c;
+ c.connect(argv[1], argv[2], std::chrono::seconds(10));
+
+ auto time_sent = std::chrono::steady_clock::now();
+
+ c.write_line(argv[3], std::chrono::seconds(10));
+
+ for (;;)
+ {
+ std::string line = c.read_line(std::chrono::seconds(10));
+
+ // Keep going until we get back the line that was sent.
+ if (line == argv[3])
+ break;
+ }
+
+ auto time_received = std::chrono::steady_clock::now();
+
+ std::cout << "Round trip time: ";
+ std::cout << std::chrono::duration_cast<
+ std::chrono::microseconds>(
+ time_received - time_sent).count();
+ std::cout << " microseconds\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp b/src/boost/libs/asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp
new file mode 100644
index 000000000..031275f73
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp
@@ -0,0 +1,199 @@
+//
+// blocking_token_tcp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/connect.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/streambuf.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <string>
+
+using boost::asio::ip::tcp;
+
+// We will use our sockets only with an io_context.
+using tcp_socket = boost::asio::basic_stream_socket<
+ tcp, boost::asio::io_context::executor_type>;
+
+//----------------------------------------------------------------------
+
+// A custom completion token that makes asynchronous operations behave as
+// though they are blocking calls with a timeout.
+struct close_after
+{
+ close_after(std::chrono::steady_clock::duration t, tcp_socket& s)
+ : timeout_(t), socket_(s)
+ {
+ }
+
+ // The maximum time to wait for an asynchronous operation to complete.
+ std::chrono::steady_clock::duration timeout_;
+
+ // The socket to be closed if the operation does not complete in time.
+ tcp_socket& socket_;
+};
+
+namespace boost {
+namespace asio {
+
+// The async_result template is specialised to allow the close_after token to
+// be used with asynchronous operations that have a completion signature of
+// void(error_code, T). Generalising this for all completion signature forms is
+// left as an exercise for the reader.
+template <typename T>
+class async_result<close_after, void(boost::system::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 boost::system::error_code& error, T t)
+ {
+ *error_ = error;
+ *t_ = t;
+ }
+
+ private:
+ friend class async_result;
+ close_after token_;
+ boost::system::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()
+ {
+ boost::asio::io_context& io_context = socket_.get_executor().context();
+
+ // Restart the io_context, as it may have been left in the "stopped" state
+ // by a previous operation.
+ io_context.restart();
+
+ // Block until the asynchronous operation has completed, or timed out. If
+ // 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_);
+
+ // If the asynchronous operation completed successfully then the io_context
+ // would have been stopped due to running out of work. If it was not
+ // stopped, then the io_context::run_for call must have timed out and the
+ // operation is still incomplete.
+ if (!io_context.stopped())
+ {
+ // Close the socket to cancel the outstanding asynchronous operation.
+ 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_;
+ }
+
+private:
+ std::chrono::steady_clock::duration timeout_;
+ tcp_socket& socket_;
+ boost::system::error_code error_;
+ T t_;
+};
+
+} // namespace asio
+} // namespace boost
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 4)
+ {
+ std::cerr << "Usage: blocking_tcp_client <host> <port> <message>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ // Resolve the host name and service to a list of endpoints.
+ auto endpoints = tcp::resolver(io_context).resolve(argv[1], argv[2]);
+
+ tcp_socket socket(io_context);
+
+ // Run an asynchronous connect operation with a timeout.
+ boost::asio::async_connect(socket, endpoints,
+ close_after(std::chrono::seconds(10), socket));
+
+ auto time_sent = std::chrono::steady_clock::now();
+
+ // Run an asynchronous write operation with a timeout.
+ std::string msg = argv[3] + std::string("\n");
+ boost::asio::async_write(socket, boost::asio::buffer(msg),
+ close_after(std::chrono::seconds(10), socket));
+
+ for (std::string input_buffer;;)
+ {
+ // Run an asynchronous read operation with a timeout.
+ std::size_t n = boost::asio::async_read_until(socket,
+ boost::asio::dynamic_buffer(input_buffer), '\n',
+ close_after(std::chrono::seconds(10), socket));
+
+ std::string line(input_buffer.substr(0, n - 1));
+ input_buffer.erase(0, n);
+
+ // Keep going until we get back the line that was sent.
+ if (line == argv[3])
+ break;
+ }
+
+ auto time_received = std::chrono::steady_clock::now();
+
+ std::cout << "Round trip time: ";
+ std::cout << std::chrono::duration_cast<
+ std::chrono::microseconds>(
+ time_received - time_sent).count();
+ std::cout << " microseconds\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/timeouts/blocking_udp_client.cpp b/src/boost/libs/asio/example/cpp11/timeouts/blocking_udp_client.cpp
new file mode 100644
index 000000000..c769e3e7b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/timeouts/blocking_udp_client.cpp
@@ -0,0 +1,155 @@
+//
+// blocking_udp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+
+using boost::asio::ip::udp;
+using std::placeholders::_1;
+using std::placeholders::_2;
+
+//----------------------------------------------------------------------
+
+//
+// This class manages socket timeouts by running the io_context using the timed
+// io_context::run_for() member function. Each asynchronous operation is given
+// a timeout within which it must complete. The socket operations themselves
+// use std::bind to specify the completion handler:
+//
+// +---------------+
+// | |
+// | receive |
+// | |
+// +---------------+
+// |
+// async_- | +----------------+
+// receive() | | |
+// +--->| handle_receive |
+// | |
+// +----------------+
+//
+// For a given socket operation, the client object runs the io_context to block
+// thread execution until the operation completes or the timeout is reached. If
+// the io_context::run_for() function times out, the socket is closed and the
+// outstanding asynchronous operation is cancelled.
+//
+class client
+{
+public:
+ client(const udp::endpoint& listen_endpoint)
+ : socket_(io_context_, listen_endpoint)
+ {
+ }
+
+ std::size_t receive(const boost::asio::mutable_buffer& buffer,
+ std::chrono::steady_clock::duration timeout,
+ boost::system::error_code& error)
+ {
+ // Start the asynchronous operation. The handle_receive function used as a
+ // callback will update the error and length variables.
+ std::size_t length = 0;
+ socket_.async_receive(boost::asio::buffer(buffer),
+ std::bind(&client::handle_receive, _1, _2, &error, &length));
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ return length;
+ }
+
+private:
+ void run(std::chrono::steady_clock::duration timeout)
+ {
+ // Restart the io_context, as it may have been left in the "stopped" state
+ // by a previous operation.
+ io_context_.restart();
+
+ // Block until the asynchronous operation has completed, or timed out. If
+ // 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);
+
+ // If the asynchronous operation completed successfully then the io_context
+ // would have been stopped due to running out of work. If it was not
+ // stopped, then the io_context::run_for call must have timed out.
+ if (!io_context_.stopped())
+ {
+ // Cancel the outstanding asynchronous operation.
+ socket_.cancel();
+
+ // Run the io_context again until the operation completes.
+ io_context_.run();
+ }
+ }
+
+ static void handle_receive(
+ const boost::system::error_code& error, std::size_t length,
+ boost::system::error_code* out_error, std::size_t* out_length)
+ {
+ *out_error = error;
+ *out_length = length;
+ }
+
+private:
+ boost::asio::io_context io_context_;
+ udp::socket socket_;
+};
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ using namespace std; // For atoi.
+
+ if (argc != 3)
+ {
+ std::cerr << "Usage: blocking_udp_client <listen_addr> <listen_port>\n";
+ return 1;
+ }
+
+ udp::endpoint listen_endpoint(
+ boost::asio::ip::make_address(argv[1]),
+ std::atoi(argv[2]));
+
+ client c(listen_endpoint);
+
+ for (;;)
+ {
+ char data[1024];
+ boost::system::error_code error;
+ std::size_t n = c.receive(boost::asio::buffer(data),
+ std::chrono::seconds(10), error);
+
+ if (error)
+ {
+ std::cout << "Receive error: " << error.message() << "\n";
+ }
+ else
+ {
+ std::cout << "Received: ";
+ std::cout.write(data, n);
+ std::cout << "\n";
+ }
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/timeouts/server.cpp b/src/boost/libs/asio/example/cpp11/timeouts/server.cpp
new file mode 100644
index 000000000..e693791b4
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/timeouts/server.cpp
@@ -0,0 +1,433 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <algorithm>
+#include <cstdlib>
+#include <deque>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <string>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/write.hpp>
+
+using boost::asio::steady_timer;
+using boost::asio::ip::tcp;
+using boost::asio::ip::udp;
+
+//----------------------------------------------------------------------
+
+class subscriber
+{
+public:
+ virtual ~subscriber() = default;
+ virtual void deliver(const std::string& msg) = 0;
+};
+
+typedef std::shared_ptr<subscriber> subscriber_ptr;
+
+//----------------------------------------------------------------------
+
+class channel
+{
+public:
+ void join(subscriber_ptr subscriber)
+ {
+ subscribers_.insert(subscriber);
+ }
+
+ void leave(subscriber_ptr subscriber)
+ {
+ subscribers_.erase(subscriber);
+ }
+
+ void deliver(const std::string& msg)
+ {
+ for (const auto& s : subscribers_)
+ {
+ s->deliver(msg);
+ }
+ }
+
+private:
+ std::set<subscriber_ptr> subscribers_;
+};
+
+//----------------------------------------------------------------------
+
+//
+// This class manages socket timeouts by applying the concept of a deadline.
+// Some asynchronous operations are given deadlines by which they must complete.
+// Deadlines are enforced by two "actors" that persist for the lifetime of the
+// session object, one for input and one for output:
+//
+// +----------------+ +----------------+
+// | | | |
+// | check_deadline |<-------+ | check_deadline |<-------+
+// | | | | | |
+// +----------------+ | +----------------+ |
+// | | | |
+// async_wait() | +----------------+ async_wait() | +----------------+
+// on input | | lambda | on output | | lambda |
+// deadline +--->| in | deadline +--->| in |
+// | check_deadline | | check_deadline |
+// +----------------+ +----------------+
+//
+// If either deadline actor determines that the corresponding deadline has
+// expired, the socket is closed and any outstanding operations are cancelled.
+//
+// The input actor reads messages from the socket, where messages are delimited
+// by the newline character:
+//
+// +-------------+
+// | |
+// | read_line |<----+
+// | | |
+// +-------------+ |
+// | |
+// async_- | +-------------+
+// read_- | | lambda |
+// until() +--->| in |
+// | read_line |
+// +-------------+
+//
+// The deadline for receiving a complete message is 30 seconds. If a non-empty
+// message is received, it is delivered to all subscribers. If a heartbeat (a
+// message that consists of a single newline character) is received, a heartbeat
+// is enqueued for the client, provided there are no other messages waiting to
+// be sent.
+//
+// The output actor is responsible for sending messages to the client:
+//
+// +----------------+
+// | |<---------------------+
+// | await_output | |
+// | |<-------+ |
+// +----------------+ | |
+// | | | |
+// | async_- | +----------------+ |
+// | wait() | | lambda | |
+// | +->| in | |
+// | | await_output | |
+// | +----------------+ |
+// V |
+// +--------------+ +--------------+
+// | | async_write() | lambda |
+// | write_line |-------------->| in |
+// | | | write_line |
+// +--------------+ +--------------+
+//
+// The output actor first waits for an output message to be enqueued. It does
+// this by using a steady_timer as an asynchronous condition variable. The
+// steady_timer will be signalled whenever the output queue is non-empty.
+//
+// Once a message is available, it is sent to the client. The deadline for
+// sending a complete message is 30 seconds. After the message is successfully
+// sent, the output actor again waits for the output queue to become non-empty.
+//
+class tcp_session
+ : public subscriber,
+ public std::enable_shared_from_this<tcp_session>
+{
+public:
+ tcp_session(tcp::socket socket, channel& ch)
+ : channel_(ch),
+ socket_(std::move(socket))
+ {
+ input_deadline_.expires_at(steady_timer::time_point::max());
+ output_deadline_.expires_at(steady_timer::time_point::max());
+
+ // The non_empty_output_queue_ steady_timer is set to the maximum time
+ // point whenever the output queue is empty. This ensures that the output
+ // actor stays asleep until a message is put into the queue.
+ non_empty_output_queue_.expires_at(steady_timer::time_point::max());
+ }
+
+ // Called by the server object to initiate the four actors.
+ void start()
+ {
+ channel_.join(shared_from_this());
+
+ read_line();
+ check_deadline(input_deadline_);
+
+ await_output();
+ check_deadline(output_deadline_);
+ }
+
+private:
+ void stop()
+ {
+ channel_.leave(shared_from_this());
+
+ boost::system::error_code ignored_error;
+ socket_.close(ignored_error);
+ input_deadline_.cancel();
+ non_empty_output_queue_.cancel();
+ output_deadline_.cancel();
+ }
+
+ bool stopped() const
+ {
+ return !socket_.is_open();
+ }
+
+ void deliver(const std::string& msg) override
+ {
+ output_queue_.push_back(msg + "\n");
+
+ // Signal that the output queue contains messages. Modifying the expiry
+ // will wake the output actor, if it is waiting on the timer.
+ non_empty_output_queue_.expires_at(steady_timer::time_point::min());
+ }
+
+ void read_line()
+ {
+ // Set a deadline for the read operation.
+ input_deadline_.expires_after(std::chrono::seconds(30));
+
+ // Start an asynchronous operation to read a newline-delimited message.
+ auto self(shared_from_this());
+ boost::asio::async_read_until(socket_,
+ boost::asio::dynamic_buffer(input_buffer_), '\n',
+ [this, self](const boost::system::error_code& error, std::size_t n)
+ {
+ // Check if the session was stopped while the operation was pending.
+ if (stopped())
+ return;
+
+ if (!error)
+ {
+ // Extract the newline-delimited message from the buffer.
+ std::string msg(input_buffer_.substr(0, n - 1));
+ input_buffer_.erase(0, n);
+
+ if (!msg.empty())
+ {
+ channel_.deliver(msg);
+ }
+ else
+ {
+
+ // We received a heartbeat message from the client. If there's
+ // nothing else being sent or ready to be sent, send a heartbeat
+ // right back.
+ if (output_queue_.empty())
+ {
+ output_queue_.push_back("\n");
+
+ // Signal that the output queue contains messages. Modifying
+ // the expiry will wake the output actor, if it is waiting on
+ // the timer.
+ non_empty_output_queue_.expires_at(
+ steady_timer::time_point::min());
+ }
+ }
+
+ read_line();
+ }
+ else
+ {
+ stop();
+ }
+ });
+ }
+
+ void await_output()
+ {
+ auto self(shared_from_this());
+ non_empty_output_queue_.async_wait(
+ [this, self](const boost::system::error_code& /*error*/)
+ {
+ // Check if the session was stopped while the operation was pending.
+ if (stopped())
+ return;
+
+ if (output_queue_.empty())
+ {
+ // There are no messages that are ready to be sent. The actor goes
+ // to sleep by waiting on the non_empty_output_queue_ timer. When a
+ // new message is added, the timer will be modified and the actor
+ // will wake.
+ non_empty_output_queue_.expires_at(steady_timer::time_point::max());
+ await_output();
+ }
+ else
+ {
+ write_line();
+ }
+ });
+ }
+
+ void write_line()
+ {
+ // Set a deadline for the write operation.
+ output_deadline_.expires_after(std::chrono::seconds(30));
+
+ // Start an asynchronous operation to send a message.
+ auto self(shared_from_this());
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(output_queue_.front()),
+ [this, self](const boost::system::error_code& error, std::size_t /*n*/)
+ {
+ // Check if the session was stopped while the operation was pending.
+ if (stopped())
+ return;
+
+ if (!error)
+ {
+ output_queue_.pop_front();
+
+ await_output();
+ }
+ else
+ {
+ stop();
+ }
+ });
+ }
+
+ void check_deadline(steady_timer& deadline)
+ {
+ auto self(shared_from_this());
+ deadline.async_wait(
+ [this, self, &deadline](const boost::system::error_code& /*error*/)
+ {
+ // Check if the session was stopped while the operation was pending.
+ if (stopped())
+ return;
+
+ // Check whether the deadline has passed. We compare the deadline
+ // against the current time since a new asynchronous operation may
+ // have moved the deadline before this actor had a chance to run.
+ if (deadline.expiry() <= steady_timer::clock_type::now())
+ {
+ // The deadline has passed. Stop the session. The other actors will
+ // terminate as soon as possible.
+ stop();
+ }
+ else
+ {
+ // Put the actor back to sleep.
+ check_deadline(deadline);
+ }
+ });
+ }
+
+ channel& channel_;
+ tcp::socket socket_;
+ std::string input_buffer_;
+ steady_timer input_deadline_{socket_.get_executor()};
+ std::deque<std::string> output_queue_;
+ steady_timer non_empty_output_queue_{socket_.get_executor()};
+ steady_timer output_deadline_{socket_.get_executor()};
+};
+
+typedef std::shared_ptr<tcp_session> tcp_session_ptr;
+
+//----------------------------------------------------------------------
+
+class udp_broadcaster
+ : public subscriber
+{
+public:
+ udp_broadcaster(boost::asio::io_context& io_context,
+ const udp::endpoint& broadcast_endpoint)
+ : socket_(io_context)
+ {
+ socket_.connect(broadcast_endpoint);
+ socket_.set_option(udp::socket::broadcast(true));
+ }
+
+private:
+ void deliver(const std::string& msg)
+ {
+ boost::system::error_code ignored_error;
+ socket_.send(boost::asio::buffer(msg), 0, ignored_error);
+ }
+
+ udp::socket socket_;
+};
+
+//----------------------------------------------------------------------
+
+class server
+{
+public:
+ server(boost::asio::io_context& io_context,
+ const tcp::endpoint& listen_endpoint,
+ const udp::endpoint& broadcast_endpoint)
+ : io_context_(io_context),
+ acceptor_(io_context, listen_endpoint)
+ {
+ channel_.join(
+ std::make_shared<udp_broadcaster>(
+ io_context_, broadcast_endpoint));
+
+ accept();
+ }
+
+private:
+ void accept()
+ {
+ acceptor_.async_accept(
+ [this](const boost::system::error_code& error, tcp::socket socket)
+ {
+ if (!error)
+ {
+ std::make_shared<tcp_session>(std::move(socket), channel_)->start();
+ }
+
+ accept();
+ });
+ }
+
+ boost::asio::io_context& io_context_;
+ tcp::acceptor acceptor_;
+ channel channel_;
+};
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ using namespace std; // For atoi.
+
+ if (argc != 4)
+ {
+ std::cerr << "Usage: server <listen_port> <bcast_address> <bcast_port>\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context;
+
+ tcp::endpoint listen_endpoint(tcp::v4(), atoi(argv[1]));
+
+ udp::endpoint broadcast_endpoint(
+ boost::asio::ip::make_address(argv[2]), atoi(argv[3]));
+
+ server s(io_context, listen_endpoint, broadcast_endpoint);
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp11/timers/Jamfile.v2 b/src/boost/libs/asio/example/cpp11/timers/Jamfile.v2
new file mode 100644
index 000000000..7c57391ed
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/timers/Jamfile.v2
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+exe time_t_timer
+ : time_t_timer.cpp
+ /boost/system//boost_system
+ /boost/chrono//boost_chrono
+ : <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
diff --git a/src/boost/libs/asio/example/cpp11/timers/time_t_timer.cpp b/src/boost/libs/asio/example/cpp11/timers/time_t_timer.cpp
new file mode 100644
index 000000000..9ac53d343
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp11/timers/time_t_timer.cpp
@@ -0,0 +1,106 @@
+//
+// time_t_timer.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio.hpp>
+#include <ctime>
+#include <chrono>
+#include <iostream>
+
+// A custom implementation of the Clock concept from the standard C++ library.
+struct time_t_clock
+{
+ // The duration type.
+ typedef std::chrono::steady_clock::duration duration;
+
+ // The duration's underlying arithmetic representation.
+ typedef duration::rep rep;
+
+ // The ratio representing the duration's tick period.
+ typedef duration::period period;
+
+ // An absolute time point represented using the clock.
+ typedef std::chrono::time_point<time_t_clock> time_point;
+
+ // The clock is not monotonically increasing.
+ static constexpr bool is_steady = false;
+
+ // Get the current time.
+ static time_point now() noexcept
+ {
+ return time_point() + std::chrono::seconds(std::time(0));
+ }
+};
+
+// The boost::asio::basic_waitable_timer template accepts an optional WaitTraits
+// template parameter. The underlying time_t clock has one-second granularity,
+// so these traits may be customised to reduce the latency between the clock
+// ticking over and a wait operation's completion. When the timeout is near
+// (less than one second away) we poll the clock more frequently to detect the
+// time change closer to when it occurs. The user can select the appropriate
+// trade off between accuracy and the increased CPU cost of polling. In extreme
+// cases, a zero duration may be returned to make the timers as accurate as
+// possible, albeit with 100% CPU usage.
+struct time_t_wait_traits
+{
+ // Determine how long until the clock should be next polled to determine
+ // whether the duration has elapsed.
+ static time_t_clock::duration to_wait_duration(
+ const time_t_clock::duration& d)
+ {
+ if (d > std::chrono::seconds(1))
+ return d - std::chrono::seconds(1);
+ else if (d > std::chrono::seconds(0))
+ return std::chrono::milliseconds(10);
+ else
+ return std::chrono::seconds(0);
+ }
+
+ // Determine how long until the clock should be next polled to determine
+ // whether the absoluate time has been reached.
+ static time_t_clock::duration to_wait_duration(
+ const time_t_clock::time_point& t)
+ {
+ return to_wait_duration(t - time_t_clock::now());
+ }
+};
+
+typedef boost::asio::basic_waitable_timer<
+ time_t_clock, time_t_wait_traits> time_t_timer;
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context;
+
+ time_t_timer timer(io_context);
+
+ timer.expires_after(std::chrono::seconds(5));
+ std::cout << "Starting synchronous wait\n";
+ timer.wait();
+ std::cout << "Finished synchronous wait\n";
+
+ timer.expires_after(std::chrono::seconds(5));
+ std::cout << "Starting asynchronous wait\n";
+ timer.async_wait(
+ [](const boost::system::error_code& /*error*/)
+ {
+ std::cout << "timeout\n";
+ });
+ io_context.run();
+ std::cout << "Finished asynchronous wait\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp14/executors/Jamfile.v2 b/src/boost/libs/asio/example/cpp14/executors/Jamfile.v2
new file mode 100644
index 000000000..cb7b200f6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/Jamfile.v2
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe actor : actor.cpp ;
+exe async_1 : async_1.cpp ;
+exe async_2 : async_2.cpp ;
+exe bank_account_1 : bank_account_1.cpp ;
+exe bank_account_2 : bank_account_2.cpp ;
+exe fork_join : fork_join.cpp ;
+exe pipeline : pipeline.cpp ;
+exe priority_scheduler : priority_scheduler.cpp ;
diff --git a/src/boost/libs/asio/example/cpp14/executors/actor.cpp b/src/boost/libs/asio/example/cpp14/executors/actor.cpp
new file mode 100644
index 000000000..7046e7ba9
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/actor.cpp
@@ -0,0 +1,281 @@
+#include <boost/asio/ts/executor.hpp>
+#include <condition_variable>
+#include <deque>
+#include <memory>
+#include <mutex>
+#include <typeinfo>
+#include <vector>
+
+using boost::asio::defer;
+using boost::asio::executor;
+using boost::asio::post;
+using boost::asio::strand;
+using boost::asio::system_executor;
+
+//------------------------------------------------------------------------------
+// A tiny actor framework
+// ~~~~~~~~~~~~~~~~~~~~~~
+
+class actor;
+
+// Used to identify the sender and recipient of messages.
+typedef actor* actor_address;
+
+// Base class for all registered message handlers.
+class message_handler_base
+{
+public:
+ virtual ~message_handler_base() {}
+
+ // Used to determine which message handlers receive an incoming message.
+ virtual const std::type_info& message_id() const = 0;
+};
+
+// Base class for a handler for a specific message type.
+template <class Message>
+class message_handler : public message_handler_base
+{
+public:
+ // Handle an incoming message.
+ virtual void handle_message(Message msg, actor_address from) = 0;
+};
+
+// Concrete message handler for a specific message type.
+template <class Actor, class Message>
+class mf_message_handler : public message_handler<Message>
+{
+public:
+ // Construct a message handler to invoke the specified member function.
+ mf_message_handler(void (Actor::* mf)(Message, actor_address), Actor* a)
+ : function_(mf), actor_(a)
+ {
+ }
+
+ // Used to determine which message handlers receive an incoming message.
+ virtual const std::type_info& message_id() const
+ {
+ return typeid(Message);
+ }
+
+ // Handle an incoming message.
+ virtual void handle_message(Message msg, actor_address from)
+ {
+ (actor_->*function_)(std::move(msg), from);
+ }
+
+ // Determine whether the message handler represents the specified function.
+ bool is_function(void (Actor::* mf)(Message, actor_address)) const
+ {
+ return mf == function_;
+ }
+
+private:
+ void (Actor::* function_)(Message, actor_address);
+ Actor* actor_;
+};
+
+// Base class for all actors.
+class actor
+{
+public:
+ virtual ~actor()
+ {
+ }
+
+ // Obtain the actor's address for use as a message sender or recipient.
+ actor_address address()
+ {
+ return this;
+ }
+
+ // Send a message from one actor to another.
+ template <class Message>
+ friend void send(Message msg, actor_address from, actor_address to)
+ {
+ // Execute the message handler in the context of the target's executor.
+ post(to->executor_,
+ [=, msg=std::move(msg)]
+ {
+ to->call_handler(std::move(msg), from);
+ });
+ }
+
+protected:
+ // Construct the actor to use the specified executor for all message handlers.
+ actor(executor e)
+ : executor_(std::move(e))
+ {
+ }
+
+ // Register a handler for a specific message type. Duplicates are permitted.
+ template <class Actor, class Message>
+ void register_handler(void (Actor::* mf)(Message, actor_address))
+ {
+ handlers_.push_back(
+ std::make_shared<mf_message_handler<Actor, Message>>(
+ mf, static_cast<Actor*>(this)));
+ }
+
+ // Deregister a handler. Removes only the first matching handler.
+ template <class Actor, class Message>
+ void deregister_handler(void (Actor::* mf)(Message, actor_address))
+ {
+ const std::type_info& id = typeid(Message);
+ for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter)
+ {
+ if ((*iter)->message_id() == id)
+ {
+ auto mh = static_cast<mf_message_handler<Actor, Message>*>(iter->get());
+ if (mh->is_function(mf))
+ {
+ handlers_.erase(iter);
+ return;
+ }
+ }
+ }
+ }
+
+ // Send a message from within a message handler.
+ template <class Message>
+ void tail_send(Message msg, actor_address to)
+ {
+ // Execute the message handler in the context of the target's executor.
+ defer(to->executor_,
+ [=, msg=std::move(msg), from=this]
+ {
+ to->call_handler(std::move(msg), from);
+ });
+ }
+
+private:
+ // Find the matching message handlers, if any, and call them.
+ template <class Message>
+ void call_handler(Message msg, actor_address from)
+ {
+ const std::type_info& message_id = typeid(Message);
+ for (auto& h: handlers_)
+ {
+ if (h->message_id() == message_id)
+ {
+ auto mh = static_cast<message_handler<Message>*>(h.get());
+ mh->handle_message(msg, from);
+ }
+ }
+ }
+
+ // All messages associated with a single actor object should be processed
+ // non-concurrently. We use a strand to ensure non-concurrent execution even
+ // if the underlying executor may use multiple threads.
+ strand<executor> executor_;
+
+ std::vector<std::shared_ptr<message_handler_base>> handlers_;
+};
+
+// A concrete actor that allows synchronous message retrieval.
+template <class Message>
+class receiver : public actor
+{
+public:
+ receiver()
+ : actor(system_executor())
+ {
+ register_handler(&receiver::message_handler);
+ }
+
+ // Block until a message has been received.
+ Message wait()
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ condition_.wait(lock, [this]{ return !message_queue_.empty(); });
+ Message msg(std::move(message_queue_.front()));
+ message_queue_.pop_front();
+ return msg;
+ }
+
+private:
+ // Handle a new message by adding it to the queue and waking a waiter.
+ void message_handler(Message msg, actor_address /* from */)
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ message_queue_.push_back(std::move(msg));
+ condition_.notify_one();
+ }
+
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::deque<Message> message_queue_;
+};
+
+//------------------------------------------------------------------------------
+
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+
+using boost::asio::thread_pool;
+
+class member : public actor
+{
+public:
+ explicit member(executor e)
+ : actor(std::move(e))
+ {
+ register_handler(&member::init_handler);
+ }
+
+private:
+ void init_handler(actor_address next, actor_address from)
+ {
+ next_ = next;
+ caller_ = from;
+
+ register_handler(&member::token_handler);
+ deregister_handler(&member::init_handler);
+ }
+
+ void token_handler(int token, actor_address /*from*/)
+ {
+ int msg(token);
+ actor_address to(caller_);
+
+ if (token > 0)
+ {
+ msg = token - 1;
+ to = next_;
+ }
+
+ tail_send(msg, to);
+ }
+
+ actor_address next_;
+ actor_address caller_;
+};
+
+int main()
+{
+ const std::size_t num_threads = 16;
+ const int num_hops = 50000000;
+ const std::size_t num_actors = 503;
+ const int token_value = (num_hops + num_actors - 1) / num_actors;
+ const std::size_t actors_per_thread = num_actors / num_threads;
+
+ struct single_thread_pool : thread_pool { single_thread_pool() : thread_pool(1) {} };
+ single_thread_pool pools[num_threads];
+ std::vector<std::shared_ptr<member>> members(num_actors);
+ receiver<int> rcvr;
+
+ // Create the member actors.
+ for (std::size_t i = 0; i < num_actors; ++i)
+ members[i] = std::make_shared<member>(pools[(i / actors_per_thread) % num_threads].get_executor());
+
+ // Initialise the actors by passing each one the address of the next actor in the ring.
+ for (std::size_t i = num_actors, next_i = 0; i > 0; next_i = --i)
+ send(members[next_i]->address(), rcvr.address(), members[i - 1]->address());
+
+ // Send exactly one token to each actor, all with the same initial value, rounding up if required.
+ for (std::size_t i = 0; i < num_actors; ++i)
+ send(token_value, rcvr.address(), members[i]->address());
+
+ // Wait for all signal messages, indicating the tokens have all reached zero.
+ for (std::size_t i = 0; i < num_actors; ++i)
+ rcvr.wait();
+}
diff --git a/src/boost/libs/asio/example/cpp14/executors/async_1.cpp b/src/boost/libs/asio/example/cpp14/executors/async_1.cpp
new file mode 100644
index 000000000..db72563a8
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/async_1.cpp
@@ -0,0 +1,47 @@
+#include <boost/asio/ts/executor.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+#include <string>
+
+using boost::asio::bind_executor;
+using boost::asio::dispatch;
+using boost::asio::make_work_guard;
+using boost::asio::post;
+using boost::asio::thread_pool;
+
+// A function to asynchronously read a single line from an input stream.
+template <class Handler>
+void async_getline(std::istream& is, Handler handler)
+{
+ // Create executor_work for the handler's associated executor.
+ auto work = make_work_guard(handler);
+
+ // Post a function object to do the work asynchronously.
+ post([&is, work, handler=std::move(handler)]() mutable
+ {
+ std::string line;
+ std::getline(is, line);
+
+ // Pass the result to the handler, via the associated executor.
+ dispatch(work.get_executor(),
+ [line=std::move(line), handler=std::move(handler)]() mutable
+ {
+ handler(std::move(line));
+ });
+ });
+}
+
+int main()
+{
+ thread_pool pool;
+
+ std::cout << "Enter a line: ";
+
+ async_getline(std::cin,
+ bind_executor(pool, [](std::string line)
+ {
+ std::cout << "Line: " << line << "\n";
+ }));
+
+ pool.join();
+}
diff --git a/src/boost/libs/asio/example/cpp14/executors/async_2.cpp b/src/boost/libs/asio/example/cpp14/executors/async_2.cpp
new file mode 100644
index 000000000..6f40a902c
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/async_2.cpp
@@ -0,0 +1,68 @@
+#include <boost/asio/ts/executor.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+#include <string>
+
+using boost::asio::bind_executor;
+using boost::asio::dispatch;
+using boost::asio::get_associated_executor;
+using boost::asio::make_work_guard;
+using boost::asio::post;
+using boost::asio::thread_pool;
+
+// A function to asynchronously read a single line from an input stream.
+template <class Handler>
+void async_getline(std::istream& is, Handler handler)
+{
+ // Create executor_work for the handler's associated executor.
+ auto work = make_work_guard(handler);
+
+ // Post a function object to do the work asynchronously.
+ post([&is, work, handler=std::move(handler)]() mutable
+ {
+ std::string line;
+ std::getline(is, line);
+
+ // Pass the result to the handler, via the associated executor.
+ dispatch(work.get_executor(),
+ [line=std::move(line), handler=std::move(handler)]() mutable
+ {
+ handler(std::move(line));
+ });
+ });
+}
+
+// A function to asynchronously read multiple lines from an input stream.
+template <class Handler>
+void async_getlines(std::istream& is, std::string init, Handler handler)
+{
+ // Get the final handler's associated executor.
+ auto ex = get_associated_executor(handler);
+
+ // Use the associated executor for each operation in the composition.
+ async_getline(is,
+ bind_executor(ex,
+ [&is, lines=std::move(init), handler=std::move(handler)]
+ (std::string line) mutable
+ {
+ if (line.empty())
+ handler(lines);
+ else
+ async_getlines(is, lines + line + "\n", std::move(handler));
+ }));
+}
+
+int main()
+{
+ thread_pool pool;
+
+ std::cout << "Enter text, terminating with a blank line:\n";
+
+ async_getlines(std::cin, "",
+ bind_executor(pool, [](std::string lines)
+ {
+ std::cout << "Lines:\n" << lines << "\n";
+ }));
+
+ pool.join();
+}
diff --git a/src/boost/libs/asio/example/cpp14/executors/bank_account_1.cpp b/src/boost/libs/asio/example/cpp14/executors/bank_account_1.cpp
new file mode 100644
index 000000000..6464b48d3
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/bank_account_1.cpp
@@ -0,0 +1,54 @@
+#include <boost/asio/ts/executor.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+
+using boost::asio::post;
+using boost::asio::thread_pool;
+
+// Traditional active object pattern.
+// Member functions do not block.
+
+class bank_account
+{
+ int balance_ = 0;
+ mutable thread_pool pool_{1};
+
+public:
+ void deposit(int amount)
+ {
+ post(pool_, [=]
+ {
+ balance_ += amount;
+ });
+ }
+
+ void withdraw(int amount)
+ {
+ post(pool_, [=]
+ {
+ if (balance_ >= amount)
+ balance_ -= amount;
+ });
+ }
+
+ void print_balance() const
+ {
+ post(pool_, [=]
+ {
+ std::cout << "balance = " << balance_ << "\n";
+ });
+ }
+
+ ~bank_account()
+ {
+ pool_.join();
+ }
+};
+
+int main()
+{
+ bank_account acct;
+ acct.deposit(20);
+ acct.withdraw(10);
+ acct.print_balance();
+}
diff --git a/src/boost/libs/asio/example/cpp14/executors/bank_account_2.cpp b/src/boost/libs/asio/example/cpp14/executors/bank_account_2.cpp
new file mode 100644
index 000000000..8de9a3cc2
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/bank_account_2.cpp
@@ -0,0 +1,53 @@
+#include <boost/asio/ts/executor.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+
+using boost::asio::post;
+using boost::asio::thread_pool;
+using boost::asio::use_future;
+
+// Traditional active object pattern.
+// Member functions block until operation is finished.
+
+class bank_account
+{
+ int balance_ = 0;
+ mutable thread_pool pool_{1};
+
+public:
+ void deposit(int amount)
+ {
+ post(pool_,
+ use_future([=]
+ {
+ balance_ += amount;
+ })).get();
+ }
+
+ void withdraw(int amount)
+ {
+ post(pool_,
+ use_future([=]
+ {
+ if (balance_ >= amount)
+ balance_ -= amount;
+ })).get();
+ }
+
+ int balance() const
+ {
+ return post(pool_,
+ use_future([=]
+ {
+ return balance_;
+ })).get();
+ }
+};
+
+int main()
+{
+ bank_account acct;
+ acct.deposit(20);
+ acct.withdraw(10);
+ std::cout << "balance = " << acct.balance() << "\n";
+}
diff --git a/src/boost/libs/asio/example/cpp14/executors/fork_join.cpp b/src/boost/libs/asio/example/cpp14/executors/fork_join.cpp
new file mode 100644
index 000000000..2d9b4f7bd
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/fork_join.cpp
@@ -0,0 +1,327 @@
+#include <boost/asio/ts/executor.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <numeric>
+
+using boost::asio::dispatch;
+using boost::asio::execution_context;
+using boost::asio::thread_pool;
+
+// A fixed-size thread pool used to implement fork/join semantics. Functions
+// are scheduled using a simple FIFO queue. Implementing work stealing, or
+// using a queue based on atomic operations, are left as tasks for the reader.
+class fork_join_pool : public execution_context
+{
+public:
+ // The constructor starts a thread pool with the specified number of threads.
+ // Note that the thread_count is not a fixed limit on the pool's concurrency.
+ // Additional threads may temporarily be added to the pool if they join a
+ // fork_executor.
+ explicit fork_join_pool(
+ std::size_t thread_count = std::thread::hardware_concurrency() * 2)
+ : use_count_(1),
+ threads_(thread_count)
+ {
+ try
+ {
+ // Ask each thread in the pool to dequeue and execute functions until
+ // it is time to shut down, i.e. the use count is zero.
+ for (thread_count_ = 0; thread_count_ < thread_count; ++thread_count_)
+ {
+ dispatch(threads_, [&]
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ while (use_count_ > 0)
+ if (!execute_next(lock))
+ condition_.wait(lock);
+ });
+ }
+ }
+ catch (...)
+ {
+ stop_threads();
+ threads_.join();
+ throw;
+ }
+ }
+
+ // The destructor waits for the pool to finish executing functions.
+ ~fork_join_pool()
+ {
+ stop_threads();
+ threads_.join();
+ }
+
+private:
+ friend class fork_executor;
+
+ // The base for all functions that are queued in the pool.
+ struct function_base
+ {
+ std::shared_ptr<std::size_t> work_count_;
+ void (*execute_)(std::shared_ptr<function_base>& p);
+ };
+
+ // Execute the next function from the queue, if any. Returns true if a
+ // function was executed, and false if the queue was empty.
+ bool execute_next(std::unique_lock<std::mutex>& lock)
+ {
+ if (queue_.empty())
+ return false;
+ auto p(queue_.front());
+ queue_.pop();
+ lock.unlock();
+ execute(lock, p);
+ return true;
+ }
+
+ // Execute a function and decrement the outstanding work.
+ void execute(std::unique_lock<std::mutex>& lock,
+ std::shared_ptr<function_base>& p)
+ {
+ std::shared_ptr<std::size_t> work_count(std::move(p->work_count_));
+ try
+ {
+ p->execute_(p);
+ lock.lock();
+ do_work_finished(work_count);
+ }
+ catch (...)
+ {
+ lock.lock();
+ do_work_finished(work_count);
+ throw;
+ }
+ }
+
+ // Increment outstanding work.
+ void do_work_started(const std::shared_ptr<std::size_t>& work_count) noexcept
+ {
+ if (++(*work_count) == 1)
+ ++use_count_;
+ }
+
+ // Decrement outstanding work. Notify waiting threads if we run out.
+ void do_work_finished(const std::shared_ptr<std::size_t>& work_count) noexcept
+ {
+ if (--(*work_count) == 0)
+ {
+ --use_count_;
+ condition_.notify_all();
+ }
+ }
+
+ // Dispatch a function, executing it immediately if the queue is already
+ // loaded. Otherwise adds the function to the queue and wakes a thread.
+ void do_dispatch(std::shared_ptr<function_base> p,
+ const std::shared_ptr<std::size_t>& work_count)
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (queue_.size() > thread_count_ * 16)
+ {
+ do_work_started(work_count);
+ lock.unlock();
+ execute(lock, p);
+ }
+ else
+ {
+ queue_.push(p);
+ do_work_started(work_count);
+ condition_.notify_one();
+ }
+ }
+
+ // Add a function to the queue and wake a thread.
+ void do_post(std::shared_ptr<function_base> p,
+ const std::shared_ptr<std::size_t>& work_count)
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ queue_.push(p);
+ do_work_started(work_count);
+ condition_.notify_one();
+ }
+
+ // Ask all threads to shut down.
+ void stop_threads()
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ --use_count_;
+ condition_.notify_all();
+ }
+
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::queue<std::shared_ptr<function_base>> queue_;
+ std::size_t use_count_;
+ std::size_t thread_count_;
+ thread_pool threads_;
+};
+
+// A class that satisfies the Executor requirements. Every function or piece of
+// work associated with a fork_executor is part of a single, joinable group.
+class fork_executor
+{
+public:
+ fork_executor(fork_join_pool& ctx)
+ : context_(ctx),
+ work_count_(std::make_shared<std::size_t>(0))
+ {
+ }
+
+ fork_join_pool& context() const noexcept
+ {
+ return context_;
+ }
+
+ void on_work_started() const noexcept
+ {
+ std::lock_guard<std::mutex> lock(context_.mutex_);
+ context_.do_work_started(work_count_);
+ }
+
+ void on_work_finished() const noexcept
+ {
+ std::lock_guard<std::mutex> lock(context_.mutex_);
+ context_.do_work_finished(work_count_);
+ }
+
+ template <class Func, class Alloc>
+ void dispatch(Func&& f, const Alloc& a) const
+ {
+ auto p(std::allocate_shared<function<Func>>(
+ typename std::allocator_traits<Alloc>::template rebind_alloc<char>(a),
+ std::move(f), work_count_));
+ context_.do_dispatch(p, work_count_);
+ }
+
+ template <class Func, class Alloc>
+ void post(Func f, const Alloc& a) const
+ {
+ auto p(std::allocate_shared<function<Func>>(
+ typename std::allocator_traits<Alloc>::template rebind_alloc<char>(a),
+ std::move(f), work_count_));
+ context_.do_post(p, work_count_);
+ }
+
+ template <class Func, class Alloc>
+ void defer(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ friend bool operator==(const fork_executor& a,
+ const fork_executor& b) noexcept
+ {
+ return a.work_count_ == b.work_count_;
+ }
+
+ friend bool operator!=(const fork_executor& a,
+ const fork_executor& b) noexcept
+ {
+ return a.work_count_ != b.work_count_;
+ }
+
+ // Block until all work associated with the executor is complete. While it is
+ // waiting, the thread may be borrowed to execute functions from the queue.
+ void join() const
+ {
+ std::unique_lock<std::mutex> lock(context_.mutex_);
+ while (*work_count_ > 0)
+ if (!context_.execute_next(lock))
+ context_.condition_.wait(lock);
+ }
+
+private:
+ template <class Func>
+ struct function : fork_join_pool::function_base
+ {
+ explicit function(Func f, const std::shared_ptr<std::size_t>& w)
+ : function_(std::move(f))
+ {
+ work_count_ = w;
+ execute_ = [](std::shared_ptr<fork_join_pool::function_base>& p)
+ {
+ Func tmp(std::move(static_cast<function*>(p.get())->function_));
+ p.reset();
+ tmp();
+ };
+ }
+
+ Func function_;
+ };
+
+ fork_join_pool& context_;
+ std::shared_ptr<std::size_t> work_count_;
+};
+
+// Helper class to automatically join a fork_executor when exiting a scope.
+class join_guard
+{
+public:
+ explicit join_guard(const fork_executor& ex) : ex_(ex) {}
+ join_guard(const join_guard&) = delete;
+ join_guard(join_guard&&) = delete;
+ ~join_guard() { ex_.join(); }
+
+private:
+ fork_executor ex_;
+};
+
+//------------------------------------------------------------------------------
+
+#include <algorithm>
+#include <iostream>
+#include <random>
+#include <vector>
+
+fork_join_pool pool;
+
+template <class Iterator>
+void fork_join_sort(Iterator begin, Iterator end)
+{
+ std::size_t n = end - begin;
+ if (n > 32768)
+ {
+ {
+ fork_executor fork(pool);
+ join_guard join(fork);
+ dispatch(fork, [=]{ fork_join_sort(begin, begin + n / 2); });
+ dispatch(fork, [=]{ fork_join_sort(begin + n / 2, end); });
+ }
+ std::inplace_merge(begin, begin + n / 2, end);
+ }
+ else
+ {
+ std::sort(begin, end);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ std::cerr << "Usage: fork_join <size>\n";
+ return 1;
+ }
+
+ std::vector<double> vec(std::atoll(argv[1]));
+ std::iota(vec.begin(), vec.end(), 0);
+
+ std::random_device rd;
+ std::mt19937 g(rd());
+ std::shuffle(vec.begin(), vec.end(), g);
+
+ std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
+
+ fork_join_sort(vec.begin(), vec.end());
+
+ std::chrono::steady_clock::duration elapsed = std::chrono::steady_clock::now() - start;
+
+ std::cout << "sort took ";
+ std::cout << std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
+ std::cout << " microseconds" << std::endl;
+}
diff --git a/src/boost/libs/asio/example/cpp14/executors/pipeline.cpp b/src/boost/libs/asio/example/cpp14/executors/pipeline.cpp
new file mode 100644
index 000000000..bd837083b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/pipeline.cpp
@@ -0,0 +1,294 @@
+#include <boost/asio/ts/executor.hpp>
+#include <condition_variable>
+#include <future>
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <vector>
+#include <cctype>
+
+using boost::asio::execution_context;
+using boost::asio::executor_binder;
+using boost::asio::get_associated_executor;
+using boost::asio::post;
+using boost::asio::system_executor;
+using boost::asio::use_future;
+using boost::asio::use_service;
+
+// An executor that launches a new thread for each function submitted to it.
+// This class satisfies the Executor requirements.
+class thread_executor
+{
+private:
+ // Service to track all threads started through a thread_executor.
+ class thread_bag : public execution_context::service
+ {
+ public:
+ typedef thread_bag key_type;
+
+ explicit thread_bag(execution_context& ctx)
+ : execution_context::service(ctx)
+ {
+ }
+
+ void add_thread(std::thread&& t)
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ threads_.push_back(std::move(t));
+ }
+
+ private:
+ virtual void shutdown()
+ {
+ for (auto& t : threads_)
+ t.join();
+ }
+
+ std::mutex mutex_;
+ std::vector<std::thread> threads_;
+ };
+
+public:
+ execution_context& context() const noexcept
+ {
+ return system_executor().context();
+ }
+
+ void on_work_started() const noexcept
+ {
+ // This executor doesn't count work.
+ }
+
+ void on_work_finished() const noexcept
+ {
+ // This executor doesn't count work.
+ }
+
+ template <class Func, class Alloc>
+ void dispatch(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ template <class Func, class Alloc>
+ void post(Func f, const Alloc&) const
+ {
+ thread_bag& bag = use_service<thread_bag>(context());
+ bag.add_thread(std::thread(std::move(f)));
+ }
+
+ template <class Func, class Alloc>
+ void defer(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ friend bool operator==(const thread_executor&,
+ const thread_executor&) noexcept
+ {
+ return true;
+ }
+
+ friend bool operator!=(const thread_executor&,
+ const thread_executor&) noexcept
+ {
+ return false;
+ }
+};
+
+// Base class for all thread-safe queue implementations.
+class queue_impl_base
+{
+ template <class> friend class queue_front;
+ template <class> friend class queue_back;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ bool stop_ = false;
+};
+
+// Underlying implementation of a thread-safe queue, shared between the
+// queue_front and queue_back classes.
+template <class T>
+class queue_impl : public queue_impl_base
+{
+ template <class> friend class queue_front;
+ template <class> friend class queue_back;
+ std::queue<T> queue_;
+};
+
+// The front end of a queue between consecutive pipeline stages.
+template <class T>
+class queue_front
+{
+public:
+ typedef T value_type;
+
+ explicit queue_front(std::shared_ptr<queue_impl<T>> impl)
+ : impl_(impl)
+ {
+ }
+
+ void push(T t)
+ {
+ std::unique_lock<std::mutex> lock(impl_->mutex_);
+ impl_->queue_.push(std::move(t));
+ impl_->condition_.notify_one();
+ }
+
+ void stop()
+ {
+ std::unique_lock<std::mutex> lock(impl_->mutex_);
+ impl_->stop_ = true;
+ impl_->condition_.notify_one();
+ }
+
+private:
+ std::shared_ptr<queue_impl<T>> impl_;
+};
+
+// The back end of a queue between consecutive pipeline stages.
+template <class T>
+class queue_back
+{
+public:
+ typedef T value_type;
+
+ explicit queue_back(std::shared_ptr<queue_impl<T>> impl)
+ : impl_(impl)
+ {
+ }
+
+ bool pop(T& t)
+ {
+ std::unique_lock<std::mutex> lock(impl_->mutex_);
+ while (impl_->queue_.empty() && !impl_->stop_)
+ impl_->condition_.wait(lock);
+ if (!impl_->queue_.empty())
+ {
+ t = impl_->queue_.front();
+ impl_->queue_.pop();
+ return true;
+ }
+ return false;
+ }
+
+private:
+ std::shared_ptr<queue_impl<T>> impl_;
+};
+
+// Launch the last stage in a pipeline.
+template <class T, class F>
+std::future<void> pipeline(queue_back<T> in, F f)
+{
+ // Get the function's associated executor, defaulting to thread_executor.
+ auto ex = get_associated_executor(f, thread_executor());
+
+ // Run the function, and as we're the last stage return a future so that the
+ // caller can wait for the pipeline to finish.
+ return post(ex, use_future([in, f = std::move(f)]() mutable { f(in); }));
+}
+
+// Launch an intermediate stage in a pipeline.
+template <class T, class F, class... Tail>
+std::future<void> pipeline(queue_back<T> in, F f, Tail... t)
+{
+ // Determine the output queue type.
+ typedef typename executor_binder<F, thread_executor>::second_argument_type::value_type output_value_type;
+
+ // Create the output queue and its implementation.
+ auto out_impl = std::make_shared<queue_impl<output_value_type>>();
+ queue_front<output_value_type> out(out_impl);
+ queue_back<output_value_type> next_in(out_impl);
+
+ // Get the function's associated executor, defaulting to thread_executor.
+ auto ex = get_associated_executor(f, thread_executor());
+
+ // Run the function.
+ post(ex, [in, out, f = std::move(f)]() mutable
+ {
+ f(in, out);
+ out.stop();
+ });
+
+ // Launch the rest of the pipeline.
+ return pipeline(next_in, std::move(t)...);
+}
+
+// Launch the first stage in a pipeline.
+template <class F, class... Tail>
+std::future<void> pipeline(F f, Tail... t)
+{
+ // Determine the output queue type.
+ typedef typename executor_binder<F, thread_executor>::argument_type::value_type output_value_type;
+
+ // Create the output queue and its implementation.
+ auto out_impl = std::make_shared<queue_impl<output_value_type>>();
+ queue_front<output_value_type> out(out_impl);
+ queue_back<output_value_type> next_in(out_impl);
+
+ // Get the function's associated executor, defaulting to thread_executor.
+ auto ex = get_associated_executor(f, thread_executor());
+
+ // Run the function.
+ post(ex, [out, f = std::move(f)]() mutable
+ {
+ f(out);
+ out.stop();
+ });
+
+ // Launch the rest of the pipeline.
+ return pipeline(next_in, std::move(t)...);
+}
+
+//------------------------------------------------------------------------------
+
+#include <boost/asio/thread_pool.hpp>
+#include <iostream>
+#include <string>
+
+using boost::asio::bind_executor;
+using boost::asio::thread_pool;
+
+void reader(queue_front<std::string> out)
+{
+ std::string line;
+ while (std::getline(std::cin, line))
+ out.push(line);
+}
+
+void filter(queue_back<std::string> in, queue_front<std::string> out)
+{
+ std::string line;
+ while (in.pop(line))
+ if (line.length() > 5)
+ out.push(line);
+}
+
+void upper(queue_back<std::string> in, queue_front<std::string> out)
+{
+ std::string line;
+ while (in.pop(line))
+ {
+ std::string new_line;
+ for (char c : line)
+ new_line.push_back(std::toupper(c));
+ out.push(new_line);
+ }
+}
+
+void writer(queue_back<std::string> in)
+{
+ std::size_t count = 0;
+ std::string line;
+ while (in.pop(line))
+ std::cout << count++ << ": " << line << std::endl;
+}
+
+int main()
+{
+ thread_pool pool;
+
+ auto f = pipeline(reader, filter, bind_executor(pool, upper), writer);
+ f.wait();
+}
diff --git a/src/boost/libs/asio/example/cpp14/executors/priority_scheduler.cpp b/src/boost/libs/asio/example/cpp14/executors/priority_scheduler.cpp
new file mode 100644
index 000000000..f11853192
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/executors/priority_scheduler.cpp
@@ -0,0 +1,173 @@
+#include <boost/asio/ts/executor.hpp>
+#include <condition_variable>
+#include <iostream>
+#include <memory>
+#include <mutex>
+#include <queue>
+
+using boost::asio::dispatch;
+using boost::asio::execution_context;
+
+class priority_scheduler : public execution_context
+{
+public:
+ // A class that satisfies the Executor requirements.
+ class executor_type
+ {
+ public:
+ executor_type(priority_scheduler& ctx, int pri) noexcept
+ : context_(ctx), priority_(pri)
+ {
+ }
+
+ priority_scheduler& context() const noexcept
+ {
+ return context_;
+ }
+
+ void on_work_started() const noexcept
+ {
+ // This executor doesn't count work. Instead, the scheduler simply runs
+ // until explicitly stopped.
+ }
+
+ void on_work_finished() const noexcept
+ {
+ // This executor doesn't count work. Instead, the scheduler simply runs
+ // until explicitly stopped.
+ }
+
+ template <class Func, class Alloc>
+ void dispatch(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ template <class Func, class Alloc>
+ void post(Func f, const Alloc& a) const
+ {
+ auto p(std::allocate_shared<item<Func>>(
+ typename std::allocator_traits<
+ Alloc>::template rebind_alloc<char>(a),
+ priority_, std::move(f)));
+ std::lock_guard<std::mutex> lock(context_.mutex_);
+ context_.queue_.push(p);
+ context_.condition_.notify_one();
+ }
+
+ template <class Func, class Alloc>
+ void defer(Func&& f, const Alloc& a) const
+ {
+ post(std::forward<Func>(f), a);
+ }
+
+ friend bool operator==(const executor_type& a,
+ const executor_type& b) noexcept
+ {
+ return &a.context_ == &b.context_;
+ }
+
+ friend bool operator!=(const executor_type& a,
+ const executor_type& b) noexcept
+ {
+ return &a.context_ != &b.context_;
+ }
+
+ private:
+ priority_scheduler& context_;
+ int priority_;
+ };
+
+ ~priority_scheduler() noexcept
+ {
+ shutdown();
+ destroy();
+ }
+
+ executor_type get_executor(int pri = 0) noexcept
+ {
+ return executor_type(*const_cast<priority_scheduler*>(this), pri);
+ }
+
+ void run()
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ for (;;)
+ {
+ condition_.wait(lock, [&]{ return stopped_ || !queue_.empty(); });
+ if (stopped_)
+ return;
+ auto p(queue_.top());
+ queue_.pop();
+ lock.unlock();
+ p->execute_(p);
+ lock.lock();
+ }
+ }
+
+ void stop()
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ stopped_ = true;
+ condition_.notify_all();
+ }
+
+private:
+ struct item_base
+ {
+ int priority_;
+ void (*execute_)(std::shared_ptr<item_base>&);
+ };
+
+ template <class Func>
+ struct item : item_base
+ {
+ item(int pri, Func f) : function_(std::move(f))
+ {
+ priority_ = pri;
+ execute_ = [](std::shared_ptr<item_base>& p)
+ {
+ Func tmp(std::move(static_cast<item*>(p.get())->function_));
+ p.reset();
+ tmp();
+ };
+ }
+
+ Func function_;
+ };
+
+ struct item_comp
+ {
+ bool operator()(
+ const std::shared_ptr<item_base>& a,
+ const std::shared_ptr<item_base>& b)
+ {
+ return a->priority_ < b->priority_;
+ }
+ };
+
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::priority_queue<
+ std::shared_ptr<item_base>,
+ std::vector<std::shared_ptr<item_base>>,
+ item_comp> queue_;
+ bool stopped_ = false;
+};
+
+int main()
+{
+ priority_scheduler sched;
+ auto low = sched.get_executor(0);
+ auto med = sched.get_executor(1);
+ auto high = sched.get_executor(2);
+ dispatch(low, []{ std::cout << "1\n"; });
+ dispatch(low, []{ std::cout << "11\n"; });
+ dispatch(med, []{ std::cout << "2\n"; });
+ dispatch(med, []{ std::cout << "22\n"; });
+ dispatch(high, []{ std::cout << "3\n"; });
+ dispatch(high, []{ std::cout << "33\n"; });
+ dispatch(high, []{ std::cout << "333\n"; });
+ dispatch(sched.get_executor(-1), [&]{ sched.stop(); });
+ sched.run();
+}
diff --git a/src/boost/libs/asio/example/cpp14/operations/Jamfile.v2 b/src/boost/libs/asio/example/cpp14/operations/Jamfile.v2
new file mode 100644
index 000000000..a01b42a3a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/Jamfile.v2
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe composed_1 : composed_1.cpp ;
+exe composed_2 : composed_2.cpp ;
+exe composed_3 : composed_3.cpp ;
+exe composed_4 : composed_4.cpp ;
+exe composed_5 : composed_5.cpp ;
+exe composed_6 : composed_6.cpp ;
+exe composed_7 : composed_7.cpp ;
+exe composed_8 : composed_8.cpp ;
diff --git a/src/boost/libs/asio/example/cpp14/operations/composed_1.cpp b/src/boost/libs/asio/example/cpp14/operations/composed_1.cpp
new file mode 100644
index 000000000..4439fef6e
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/composed_1.cpp
@@ -0,0 +1,113 @@
+//
+// composed_1.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+//------------------------------------------------------------------------------
+
+// This is the simplest example of a composed asynchronous operation, where we
+// simply repackage an existing operation. The asynchronous operation
+// requirements are met by delegating responsibility to the underlying
+// operation.
+
+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 boost::asio::yield_context (used for stackful
+ // coroutines) the return type would be std::size_t, and when the completion
+ // token is boost::asio::use_future it would be std::future<std::size_t>.
+ //
+ // In C++14 we can omit the return type as it is automatically deduced from
+ // the return type of our underlying asynchronous operation
+{
+ // When delegating to the 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 boost::asio::async_write(socket,
+ boost::asio::buffer(message, std::strlen(message)),
+ std::forward<CompletionToken>(token));
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, "Testing callback\r\n",
+ [](const boost::system::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()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<std::size_t> f = async_write_message(
+ socket, "Testing future\r\n", boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ std::size_t n = f.get();
+ std::cout << n << " bytes transferred\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp14/operations/composed_2.cpp b/src/boost/libs/asio/example/cpp14/operations/composed_2.cpp
new file mode 100644
index 000000000..4c16776a5
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/composed_2.cpp
@@ -0,0 +1,131 @@
+//
+// composed_2.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+//------------------------------------------------------------------------------
+
+// This next simplest example of a composed asynchronous operation involves
+// repackaging multiple operations but choosing to invoke just one of them. All
+// of these underlying operations have the same completion signature. The
+// asynchronous operation requirements are met by delegating responsibility to
+// the underlying operations.
+
+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 boost::asio::yield_context (used for stackful
+ // coroutines) the return type would be std::size_t, and when the completion
+ // token is boost::asio::use_future it would be std::future<std::size_t>.
+ //
+ // In C++14 we can omit the return type as it is automatically deduced from
+ // the return type of our underlying asynchronous operation
+{
+ // 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(
+ boost::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 boost::asio::async_write(socket,
+ boost::asio::buffer(message, std::strlen(message)),
+ std::forward<CompletionToken>(token));
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, "Testing callback\r\n", false,
+ [](const boost::system::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()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<std::size_t> f = async_write_message(
+ socket, "Testing future\r\n", false, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ std::size_t n = f.get();
+ std::cout << n << " bytes transferred\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp14/operations/composed_3.cpp b/src/boost/libs/asio/example/cpp14/operations/composed_3.cpp
new file mode 100644
index 000000000..00ab11206
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/composed_3.cpp
@@ -0,0 +1,186 @@
+//
+// composed_3.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/bind_executor.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::asio::async_initiate function. For
+// an example that works with the Networking TS style of completion tokens,
+// please see an older version of asio.
+
+//------------------------------------------------------------------------------
+
+// In this composed operation we repackage an existing operation, but with a
+// different completion handler signature. The asynchronous operation
+// requirements are met by delegating responsibility to the underlying
+// operation.
+
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ //
+ // In C++14 we can omit the return type as it is automatically deduced from
+ // the return type of boost::asio::async_initiate.
+{
+ // 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. 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(boost::system::error_code error)
+ //
+ // The initiation function object also receives any additional arguments
+ // required to start the operation. (Note: We could have instead passed these
+ // arguments in the lambda capture set. 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.)
+ auto initiation = [](auto&& completion_handler,
+ tcp::socket& socket, const char* message)
+ {
+ // The async_write operation has a completion handler signature of:
+ //
+ // void(boost::system::error_code error, std::size n)
+ //
+ // This differs from our operation's signature in that it is also passed
+ // the number of bytes transferred as an argument of type std::size_t. We
+ // will adapt our completion handler to async_write's completion handler
+ // signature by using std::bind, which drops the additional argument.
+ //
+ // However, it is essential to the correctness of our composed operation
+ // that we preserve the executor of the user-supplied completion handler.
+ // The std::bind function will not do this for us, so we must do this by
+ // first obtaining the completion handler's associated executor (defaulting
+ // to the I/O executor - in this case the executor of the socket - if the
+ // completion handler does not have its own) ...
+ auto executor = boost::asio::get_associated_executor(
+ completion_handler, socket.get_executor());
+
+ // ... and then binding this executor to our adapted completion handler
+ // using the boost::asio::bind_executor function.
+ boost::asio::async_write(socket,
+ boost::asio::buffer(message, std::strlen(message)),
+ boost::asio::bind_executor(executor,
+ std::bind(std::forward<decltype(completion_handler)>(
+ completion_handler), std::placeholders::_1)));
+ };
+
+ // The boost::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 boost::asio::async_initiate<
+ CompletionToken, void(boost::system::error_code)>(
+ initiation, token, std::ref(socket), message);
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, "Testing callback\r\n",
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Message sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_message(
+ socket, "Testing future\r\n", boost::asio::use_future);
+
+ io_context.run();
+
+ // Get the result of the operation.
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Message sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp14/operations/composed_4.cpp b/src/boost/libs/asio/example/cpp14/operations/composed_4.cpp
new file mode 100644
index 000000000..65e0bf21b
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/composed_4.cpp
@@ -0,0 +1,201 @@
+//
+// composed_4.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/bind_executor.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::asio::async_initiate function. For
+// an example that works with the Networking TS style of completion tokens,
+// please see an older version of asio.
+
+//------------------------------------------------------------------------------
+
+// In this composed operation we repackage an existing operation, but with a
+// different completion handler signature. We will also intercept an empty
+// message as an invalid argument, and propagate the corresponding error to the
+// user. The asynchronous operation requirements are met by delegating
+// responsibility to the underlying operation.
+
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ //
+ // In C++14 we can omit the return type as it is automatically deduced from
+ // the return type of boost::asio::async_initiate.
+{
+ // 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. 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(boost::system::error_code error)
+ //
+ // The initiation function object also receives any additional arguments
+ // required to start the operation. (Note: We could have instead passed these
+ // arguments in the lambda capture set. 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.)
+ auto initiation = [](auto&& completion_handler,
+ tcp::socket& socket, const char* message)
+ {
+ // The post operation has a completion handler signature of:
+ //
+ // void()
+ //
+ // and the async_write operation has a completion handler signature of:
+ //
+ // void(boost::system::error_code error, std::size n)
+ //
+ // Both of these operations' completion handler signatures differ from our
+ // operation's completion handler signature. We will adapt our completion
+ // handler to these signatures by using std::bind, which drops the
+ // additional arguments.
+ //
+ // However, it is essential to the correctness of our composed operation
+ // that we preserve the executor of the user-supplied completion handler.
+ // The std::bind function will not do this for us, so we must do this by
+ // first obtaining the completion handler's associated executor (defaulting
+ // to the I/O executor - in this case the executor of the socket - if the
+ // completion handler does not have its own) ...
+ auto executor = boost::asio::get_associated_executor(
+ completion_handler, socket.get_executor());
+
+ // ... and then binding this executor to our adapted completion handler
+ // using the boost::asio::bind_executor function.
+ std::size_t length = std::strlen(message);
+ if (length == 0)
+ {
+ boost::asio::post(
+ boost::asio::bind_executor(executor,
+ std::bind(std::forward<decltype(completion_handler)>(
+ completion_handler), boost::asio::error::invalid_argument)));
+ }
+ else
+ {
+ boost::asio::async_write(socket,
+ boost::asio::buffer(message, length),
+ boost::asio::bind_executor(executor,
+ std::bind(std::forward<decltype(completion_handler)>(
+ completion_handler), std::placeholders::_1)));
+ }
+ };
+
+ // The boost::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 boost::asio::async_initiate<
+ CompletionToken, void(boost::system::error_code)>(
+ initiation, token, std::ref(socket), message);
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, "",
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Message sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_message(
+ socket, "", boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Message sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp14/operations/composed_5.cpp b/src/boost/libs/asio/example/cpp14/operations/composed_5.cpp
new file mode 100644
index 000000000..f7bcb169a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/composed_5.cpp
@@ -0,0 +1,238 @@
+//
+// composed_5.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::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 composed operation automatically serialises a message, using its I/O
+// streams insertion operator, before sending it on the socket. To do this, it
+// must allocate a buffer for the encoded message and ensure this buffer's
+// validity until the underlying async_write operation completes.
+
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ //
+ // In C++14 we can omit the return type as it is automatically deduced from
+ // the return type of boost::asio::async_initiate.
+{
+ // 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. 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(boost::system::error_code error)
+ //
+ // The initiation function object also receives any additional arguments
+ // required to start the operation. (Note: We could have instead passed these
+ // arguments in the lambda capture set. 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.)
+ auto initiation = [](auto&& completion_handler,
+ tcp::socket& socket, std::unique_ptr<std::string> encoded_message)
+ {
+ // In this example, the composed operation's intermediate completion
+ // handler is implemented as a hand-crafted function object, rather than
+ // using a lambda or std::bind.
+ struct intermediate_completion_handler
+ {
+ // The intermediate completion handler holds a reference to the socket so
+ // that it can obtain the I/O executor (see get_executor below).
+ tcp::socket& socket_;
+
+ // The allocated buffer for the encoded message. The std::unique_ptr
+ // smart pointer is move-only, and as a consequence our intermediate
+ // completion handler is also move-only.
+ std::unique_ptr<std::string> encoded_message_;
+
+ // The user-supplied completion handler.
+ typename std::decay<decltype(completion_handler)>::type handler_;
+
+ // The function call operator matches the completion signature of the
+ // async_write operation.
+ void operator()(const boost::system::error_code& error, std::size_t /*n*/)
+ {
+ // Deallocate the encoded message before calling the user-supplied
+ // completion handler.
+ encoded_message_.reset();
+
+ // Call the user-supplied handler with the result of the operation.
+ // The arguments must match the completion signature of our composed
+ // operation.
+ handler_(error);
+ }
+
+ // It is essential to the correctness of our composed operation that we
+ // preserve the executor of the user-supplied completion handler. With a
+ // hand-crafted function object we can do this by defining a nested type
+ // executor_type and member function get_executor. These obtain the
+ // completion handler's associated executor, and default to the I/O
+ // executor - in this case the executor of the socket - if the completion
+ // handler does not have its own.
+ using executor_type = boost::asio::associated_executor_t<
+ typename std::decay<decltype(completion_handler)>::type,
+ tcp::socket::executor_type>;
+
+ executor_type get_executor() const noexcept
+ {
+ return boost::asio::get_associated_executor(
+ handler_, socket_.get_executor());
+ }
+
+ // Although not necessary for correctness, we may also preserve the
+ // allocator of the user-supplied completion handler. This is achieved by
+ // defining a nested type allocator_type and member function
+ // get_allocator. These obtain the completion handler's associated
+ // allocator, and default to std::allocator<void> if the completion
+ // handler does not have its own.
+ using allocator_type = boost::asio::associated_allocator_t<
+ typename std::decay<decltype(completion_handler)>::type,
+ std::allocator<void>>;
+
+ allocator_type get_allocator() const noexcept
+ {
+ return boost::asio::get_associated_allocator(
+ handler_, std::allocator<void>{});
+ }
+ };
+
+ // Initiate the underlying async_write operation using our intermediate
+ // completion handler.
+ auto encoded_message_buffer = boost::asio::buffer(*encoded_message);
+ boost::asio::async_write(socket, encoded_message_buffer,
+ intermediate_completion_handler{socket, std::move(encoded_message),
+ std::forward<decltype(completion_handler)>(completion_handler)});
+ };
+
+ // Encode the message and copy it into an allocated buffer. The buffer will
+ // be maintained for the lifetime of the asynchronous operation.
+ std::ostringstream os;
+ os << message;
+ std::unique_ptr<std::string> encoded_message(new std::string(os.str()));
+
+ // The boost::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 boost::asio::async_initiate<
+ CompletionToken, void(boost::system::error_code)>(
+ initiation, token, std::ref(socket),
+ std::move(encoded_message));
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_message(socket, 123456,
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Message sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_message(
+ socket, 654.321, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Message sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp14/operations/composed_6.cpp b/src/boost/libs/asio/example/cpp14/operations/composed_6.cpp
new file mode 100644
index 000000000..8b6d01190
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/composed_6.cpp
@@ -0,0 +1,298 @@
+//
+// composed_6.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::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 composed operation shows composition of multiple underlying operations.
+// It automatically serialises a message, using its I/O streams insertion
+// operator, before sending it N times on the socket. To do this, it must
+// allocate a buffer for the encoded message and ensure this buffer's validity
+// until all underlying async_write operation complete. A one second delay is
+// inserted prior to each write operation, using a steady_timer.
+
+template <typename T, typename CompletionToken>
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ //
+ // In C++14 we can omit the return type as it is automatically deduced from
+ // the return type of boost::asio::async_initiate.
+{
+ // 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. 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(boost::system::error_code error)
+ //
+ // The initiation function object also receives any additional arguments
+ // required to start the operation. (Note: We could have instead passed these
+ // arguments in the lambda capture set. 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.)
+ auto initiation = [](auto&& completion_handler, tcp::socket& socket,
+ std::unique_ptr<std::string> encoded_message, std::size_t repeat_count,
+ std::unique_ptr<boost::asio::steady_timer> delay_timer)
+ {
+ // In this example, the composed operation's intermediate completion
+ // handler is implemented as a hand-crafted function object.
+ struct intermediate_completion_handler
+ {
+ // The intermediate completion handler holds a reference to the socket as
+ // it is used for multiple async_write operations, as well as for
+ // obtaining the I/O executor (see get_executor below).
+ tcp::socket& socket_;
+
+ // The allocated buffer for the encoded message. The std::unique_ptr
+ // smart pointer is move-only, and as a consequence our intermediate
+ // completion handler is also move-only.
+ std::unique_ptr<std::string> encoded_message_;
+
+ // The repeat count remaining.
+ std::size_t repeat_count_;
+
+ // A steady timer used for introducing a delay.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer_;
+
+ // To manage the cycle between the multiple underlying asychronous
+ // operations, our intermediate completion handler is implemented as a
+ // state machine.
+ enum { starting, waiting, writing } state_;
+
+ // 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.
+ boost::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.
+ typename std::decay<decltype(completion_handler)>::type handler_;
+
+ // By having a default value for the second argument, this function call
+ // operator matches the completion signature of both the async_write and
+ // steady_timer::async_wait operations.
+ void operator()(const boost::system::error_code& error, std::size_t = 0)
+ {
+ if (!error)
+ {
+ switch (state_)
+ {
+ case starting:
+ case writing:
+ if (repeat_count_ > 0)
+ {
+ --repeat_count_;
+ state_ = waiting;
+ delay_timer_->expires_after(std::chrono::seconds(1));
+ delay_timer_->async_wait(std::move(*this));
+ return; // Composed operation not yet complete.
+ }
+ break; // Composed operation complete, continue below.
+ case waiting:
+ state_ = writing;
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(*encoded_message_), std::move(*this));
+ return; // Composed operation not yet complete.
+ }
+ }
+
+ // 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();
+
+ // Call the user-supplied handler with the result of the operation.
+ handler_(error);
+ }
+
+ // It is essential to the correctness of our composed operation that we
+ // preserve the executor of the user-supplied completion handler. With a
+ // hand-crafted function object we can do this by defining a nested type
+ // executor_type and member function get_executor. These obtain the
+ // completion handler's associated executor, and default to the I/O
+ // executor - in this case the executor of the socket - if the completion
+ // handler does not have its own.
+ using executor_type = boost::asio::associated_executor_t<
+ typename std::decay<decltype(completion_handler)>::type,
+ tcp::socket::executor_type>;
+
+ executor_type get_executor() const noexcept
+ {
+ return boost::asio::get_associated_executor(
+ handler_, socket_.get_executor());
+ }
+
+ // Although not necessary for correctness, we may also preserve the
+ // allocator of the user-supplied completion handler. This is achieved by
+ // defining a nested type allocator_type and member function
+ // get_allocator. These obtain the completion handler's associated
+ // allocator, and default to std::allocator<void> if the completion
+ // handler does not have its own.
+ using allocator_type = boost::asio::associated_allocator_t<
+ typename std::decay<decltype(completion_handler)>::type,
+ std::allocator<void>>;
+
+ allocator_type get_allocator() const noexcept
+ {
+ return boost::asio::get_associated_allocator(
+ handler_, std::allocator<void>{});
+ }
+ };
+
+ // Initiate the underlying async_write operation using our intermediate
+ // completion handler.
+ auto encoded_message_buffer = boost::asio::buffer(*encoded_message);
+ boost::asio::async_write(socket, encoded_message_buffer,
+ intermediate_completion_handler{
+ socket, std::move(encoded_message),
+ repeat_count, std::move(delay_timer),
+ intermediate_completion_handler::starting,
+ boost::asio::make_work_guard(socket.get_executor()),
+ std::forward<decltype(completion_handler)>(completion_handler)});
+ };
+
+ // Encode the message and copy it into an allocated buffer. The buffer will
+ // be maintained for the lifetime of the composed asynchronous operation.
+ std::ostringstream os;
+ os << message;
+ std::unique_ptr<std::string> encoded_message(new std::string(os.str()));
+
+ // Create a steady_timer to be used for the delay between messages.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer(
+ new boost::asio::steady_timer(socket.get_executor()));
+
+ // The boost::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 boost::asio::async_initiate<
+ CompletionToken, void(boost::system::error_code)>(
+ initiation, token, std::ref(socket),
+ std::move(encoded_message), repeat_count,
+ std::move(delay_timer));
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_messages(socket, "Testing callback\r\n", 5,
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Messages sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_messages(
+ socket, "Testing future\r\n", 5, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Messages sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp14/operations/composed_7.cpp b/src/boost/libs/asio/example/cpp14/operations/composed_7.cpp
new file mode 100644
index 000000000..352693085
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/composed_7.cpp
@@ -0,0 +1,219 @@
+//
+// composed_7.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/compose.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::asio::async_compose function. For
+// an example that works with the Networking TS style of completion tokens,
+// please see an older version of asio.
+
+//------------------------------------------------------------------------------
+
+// This composed operation shows composition of multiple underlying operations.
+// It automatically serialises a message, using its I/O streams insertion
+// operator, before sending it N times on the socket. To do this, it must
+// allocate a buffer for the encoded message and ensure this buffer's validity
+// until all underlying async_write operation complete. A one second delay is
+// inserted prior to each write operation, using a steady_timer.
+
+template <typename T, typename CompletionToken>
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ //
+ // In C++14 we can omit the return type as it is automatically deduced from
+ // the return type of boost::asio::async_initiate.
+{
+ // Encode the message and copy it into an allocated buffer. The buffer will
+ // be maintained for the lifetime of the composed asynchronous operation.
+ std::ostringstream os;
+ os << message;
+ std::unique_ptr<std::string> encoded_message(new std::string(os.str()));
+
+ // Create a steady_timer to be used for the delay between messages.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer(
+ new boost::asio::steady_timer(socket.get_executor()));
+
+ // To manage the cycle between the multiple underlying asychronous
+ // operations, our implementation is a state machine.
+ enum { starting, waiting, writing };
+
+ // The boost::asio::async_compose function takes:
+ //
+ // - our asynchronous operation implementation,
+ // - the completion token,
+ // - the completion handler signature, and
+ // - any I/O objects (or executors) used by the operation
+ //
+ // It then wraps our implementation, which is implemented here as a state
+ // machine in a lambda, in an intermediate completion handler that meets the
+ // requirements of a conforming asynchronous operation. This includes
+ // tracking outstanding work against the I/O executors associated with the
+ // operation (in this example, this is the socket's executor).
+ //
+ // The first argument to our lambda is a reference to the enclosing
+ // intermediate completion handler. This intermediate completion handler is
+ // provided for us by the boost::asio::async_compose function, and takes care
+ // of all the details required to implement a conforming asynchronous
+ // operation. When calling an underlying asynchronous operation, we pass it
+ // this enclosing intermediate completion handler as the completion token.
+ //
+ // All arguments to our lambda after the first must be defaulted to allow the
+ // state machine to be started, as well as to allow the completion handler to
+ // match the completion signature of both the async_write and
+ // steady_timer::async_wait operations.
+ return boost::asio::async_compose<
+ CompletionToken, void(boost::system::error_code)>(
+ [
+ // The implementation holds a reference to the socket as it is used for
+ // multiple async_write operations.
+ &socket,
+
+ // The allocated buffer for the encoded message. The std::unique_ptr
+ // smart pointer is move-only, and as a consequence our lambda
+ // implementation is also move-only.
+ encoded_message = std::move(encoded_message),
+
+ // The repeat count remaining.
+ repeat_count,
+
+ // A steady timer used for introducing a delay.
+ delay_timer = std::move(delay_timer),
+
+ // To manage the cycle between the multiple underlying asychronous
+ // operations, our implementation is a state machine.
+ state = starting
+ ]
+ (
+ auto& self,
+ const boost::system::error_code& error = {},
+ std::size_t = 0
+ ) mutable
+ {
+ if (!error)
+ {
+ switch (state)
+ {
+ case starting:
+ case writing:
+ if (repeat_count > 0)
+ {
+ --repeat_count;
+ state = waiting;
+ delay_timer->expires_after(std::chrono::seconds(1));
+ delay_timer->async_wait(std::move(self));
+ return; // Composed operation not yet complete.
+ }
+ break; // Composed operation complete, continue below.
+ case waiting:
+ state = writing;
+ boost::asio::async_write(socket,
+ boost::asio::buffer(*encoded_message), std::move(self));
+ return; // Composed operation not yet complete.
+ }
+ }
+
+ // This point is reached only on completion of the entire composed
+ // operation.
+
+ // Deallocate the encoded message and delay timer before calling the
+ // user-supplied completion handler.
+ encoded_message.reset();
+ delay_timer.reset();
+
+ // Call the user-supplied handler with the result of the operation.
+ self.complete(error);
+ },
+ token, socket);
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_messages(socket, "Testing callback\r\n", 5,
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Messages sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_messages(
+ socket, "Testing future\r\n", 5, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Messages sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp14/operations/composed_8.cpp b/src/boost/libs/asio/example/cpp14/operations/composed_8.cpp
new file mode 100644
index 000000000..9fe948cd6
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp14/operations/composed_8.cpp
@@ -0,0 +1,212 @@
+//
+// composed_8.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/compose.hpp>
+#include <boost/asio/coroutine.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/use_future.hpp>
+#include <boost/asio/write.hpp>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using boost::asio::ip::tcp;
+
+// NOTE: This example requires the new boost::asio::async_compose function. For
+// an example that works with the Networking TS style of completion tokens,
+// please see an older version of asio.
+
+//------------------------------------------------------------------------------
+
+// This composed operation shows composition of multiple underlying operations,
+// using asio's stackless coroutines support to express the flow of control. It
+// automatically serialises a message, using its I/O streams insertion
+// operator, before sending it N times on the socket. To do this, it must
+// allocate a buffer for the encoded message and ensure this buffer's validity
+// until all underlying async_write operation complete. A one second delay is
+// inserted prior to each write operation, using a steady_timer.
+
+#include <boost/asio/yield.hpp>
+
+template <typename T, typename CompletionToken>
+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 boost::asio::yield_context
+ // (used for stackful coroutines) the return type would be also be void, as
+ // there is no non-error argument to the completion handler. When the
+ // completion token is boost::asio::use_future it would be std::future<void>.
+ //
+ // In C++14 we can omit the return type as it is automatically deduced from
+ // the return type of boost::asio::async_initiate.
+{
+ // Encode the message and copy it into an allocated buffer. The buffer will
+ // be maintained for the lifetime of the composed asynchronous operation.
+ std::ostringstream os;
+ os << message;
+ std::unique_ptr<std::string> encoded_message(new std::string(os.str()));
+
+ // Create a steady_timer to be used for the delay between messages.
+ std::unique_ptr<boost::asio::steady_timer> delay_timer(
+ new boost::asio::steady_timer(socket.get_executor()));
+
+ // The boost::asio::async_compose function takes:
+ //
+ // - our asynchronous operation implementation,
+ // - the completion token,
+ // - the completion handler signature, and
+ // - any I/O objects (or executors) used by the operation
+ //
+ // It then wraps our implementation, which is implemented here as a stackless
+ // coroutine in a lambda, in an intermediate completion handler that meets the
+ // requirements of a conforming asynchronous operation. This includes
+ // tracking outstanding work against the I/O executors associated with the
+ // operation (in this example, this is the socket's executor).
+ //
+ // The first argument to our lambda is a reference to the enclosing
+ // intermediate completion handler. This intermediate completion handler is
+ // provided for us by the boost::asio::async_compose function, and takes care
+ // of all the details required to implement a conforming asynchronous
+ // operation. When calling an underlying asynchronous operation, we pass it
+ // this enclosing intermediate completion handler as the completion token.
+ //
+ // All arguments to our lambda after the first must be defaulted to allow the
+ // state machine to be started, as well as to allow the completion handler to
+ // match the completion signature of both the async_write and
+ // steady_timer::async_wait operations.
+ return boost::asio::async_compose<
+ CompletionToken, void(boost::system::error_code)>(
+ [
+ // The implementation holds a reference to the socket as it is used for
+ // multiple async_write operations.
+ &socket,
+
+ // The allocated buffer for the encoded message. The std::unique_ptr
+ // smart pointer is move-only, and as a consequence our lambda
+ // implementation is also move-only.
+ encoded_message = std::move(encoded_message),
+
+ // The repeat count remaining.
+ repeat_count,
+
+ // A steady timer used for introducing a delay.
+ delay_timer = std::move(delay_timer),
+
+ // The coroutine state.
+ coro = boost::asio::coroutine()
+ ]
+ (
+ auto& self,
+ const boost::system::error_code& error = {},
+ std::size_t = 0
+ ) mutable
+ {
+ reenter (coro)
+ {
+ while (repeat_count > 0)
+ {
+ --repeat_count;
+
+ delay_timer->expires_after(std::chrono::seconds(1));
+ yield delay_timer->async_wait(std::move(self));
+ if (error)
+ break;
+
+ yield boost::asio::async_write(socket,
+ boost::asio::buffer(*encoded_message), std::move(self));
+ if (error)
+ break;
+ }
+
+ // Deallocate the encoded message and delay timer before calling the
+ // user-supplied completion handler.
+ encoded_message.reset();
+ delay_timer.reset();
+
+ // Call the user-supplied handler with the result of the operation.
+ self.complete(error);
+ }
+ },
+ token, socket);
+}
+
+#include <boost/asio/unyield.hpp>
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using a lambda as a callback.
+ async_write_messages(socket, "Testing callback\r\n", 5,
+ [](const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Messages sent\n";
+ }
+ else
+ {
+ std::cout << "Error: " << error.message() << "\n";
+ }
+ });
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_future()
+{
+ boost::asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ tcp::socket socket = acceptor.accept();
+
+ // Test our asynchronous operation using the use_future completion token.
+ // This token causes the operation's initiating function to return a future,
+ // which may be used to synchronously wait for the result of the operation.
+ std::future<void> f = async_write_messages(
+ socket, "Testing future\r\n", 5, boost::asio::use_future);
+
+ io_context.run();
+
+ try
+ {
+ // Get the result of the operation.
+ f.get();
+ std::cout << "Messages sent\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_future();
+}
diff --git a/src/boost/libs/asio/example/cpp17/coroutines_ts/chat_server.cpp b/src/boost/libs/asio/example/cpp17/coroutines_ts/chat_server.cpp
new file mode 100644
index 000000000..e233e9d6d
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp17/coroutines_ts/chat_server.cpp
@@ -0,0 +1,225 @@
+//
+// chat_server.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <cstdlib>
+#include <deque>
+#include <iostream>
+#include <list>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <boost/asio/awaitable.hpp>
+#include <boost/asio/detached.hpp>
+#include <boost/asio/co_spawn.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/redirect_error.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/use_awaitable.hpp>
+#include <boost/asio/write.hpp>
+
+using boost::asio::ip::tcp;
+using boost::asio::awaitable;
+using boost::asio::co_spawn;
+using boost::asio::detached;
+using boost::asio::redirect_error;
+using boost::asio::use_awaitable;
+
+//----------------------------------------------------------------------
+
+class chat_participant
+{
+public:
+ virtual ~chat_participant() {}
+ virtual void deliver(const std::string& msg) = 0;
+};
+
+typedef std::shared_ptr<chat_participant> chat_participant_ptr;
+
+//----------------------------------------------------------------------
+
+class chat_room
+{
+public:
+ void join(chat_participant_ptr participant)
+ {
+ participants_.insert(participant);
+ for (auto msg: recent_msgs_)
+ participant->deliver(msg);
+ }
+
+ void leave(chat_participant_ptr participant)
+ {
+ participants_.erase(participant);
+ }
+
+ void deliver(const std::string& msg)
+ {
+ recent_msgs_.push_back(msg);
+ while (recent_msgs_.size() > max_recent_msgs)
+ recent_msgs_.pop_front();
+
+ for (auto participant: participants_)
+ participant->deliver(msg);
+ }
+
+private:
+ std::set<chat_participant_ptr> participants_;
+ enum { max_recent_msgs = 100 };
+ std::deque<std::string> recent_msgs_;
+};
+
+//----------------------------------------------------------------------
+
+class chat_session
+ : public chat_participant,
+ public std::enable_shared_from_this<chat_session>
+{
+public:
+ chat_session(tcp::socket socket, chat_room& room)
+ : socket_(std::move(socket)),
+ timer_(socket_.get_executor()),
+ room_(room)
+ {
+ timer_.expires_at(std::chrono::steady_clock::time_point::max());
+ }
+
+ void start()
+ {
+ room_.join(shared_from_this());
+
+ co_spawn(socket_.get_executor(),
+ [self = shared_from_this()]{ return self->reader(); },
+ detached);
+
+ co_spawn(socket_.get_executor(),
+ [self = shared_from_this()]{ return self->writer(); },
+ detached);
+ }
+
+ void deliver(const std::string& msg)
+ {
+ write_msgs_.push_back(msg);
+ timer_.cancel_one();
+ }
+
+private:
+ awaitable<void> reader()
+ {
+ try
+ {
+ for (std::string read_msg;;)
+ {
+ std::size_t n = co_await boost::asio::async_read_until(socket_,
+ boost::asio::dynamic_buffer(read_msg, 1024), "\n", use_awaitable);
+
+ room_.deliver(read_msg.substr(0, n));
+ read_msg.erase(0, n);
+ }
+ }
+ catch (std::exception&)
+ {
+ stop();
+ }
+ }
+
+ awaitable<void> writer()
+ {
+ try
+ {
+ while (socket_.is_open())
+ {
+ if (write_msgs_.empty())
+ {
+ boost::system::error_code ec;
+ co_await timer_.async_wait(redirect_error(use_awaitable, ec));
+ }
+ else
+ {
+ co_await boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msgs_.front()), use_awaitable);
+ write_msgs_.pop_front();
+ }
+ }
+ }
+ catch (std::exception&)
+ {
+ stop();
+ }
+ }
+
+ void stop()
+ {
+ room_.leave(shared_from_this());
+ socket_.close();
+ timer_.cancel();
+ }
+
+ tcp::socket socket_;
+ boost::asio::steady_timer timer_;
+ chat_room& room_;
+ std::deque<std::string> write_msgs_;
+};
+
+//----------------------------------------------------------------------
+
+awaitable<void> listener(tcp::acceptor acceptor)
+{
+ chat_room room;
+
+ for (;;)
+ {
+ std::make_shared<chat_session>(
+ co_await acceptor.async_accept(use_awaitable),
+ room
+ )->start();
+ }
+}
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc < 2)
+ {
+ std::cerr << "Usage: chat_server <port> [<port> ...]\n";
+ return 1;
+ }
+
+ boost::asio::io_context io_context(1);
+
+ for (int i = 1; i < argc; ++i)
+ {
+ unsigned short port = std::atoi(argv[i]);
+ co_spawn(io_context,
+ [&io_context, port]
+ {
+ return listener(tcp::acceptor(io_context, {tcp::v4(), port}));
+ },
+ detached);
+ }
+
+ boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
+ signals.async_wait([&](auto, auto){ io_context.stop(); });
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/asio/example/cpp17/coroutines_ts/echo_server.cpp b/src/boost/libs/asio/example/cpp17/coroutines_ts/echo_server.cpp
new file mode 100644
index 000000000..7ca12c69a
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp17/coroutines_ts/echo_server.cpp
@@ -0,0 +1,76 @@
+//
+// echo_server.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/co_spawn.hpp>
+#include <boost/asio/detached.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdio>
+
+using boost::asio::ip::tcp;
+using boost::asio::awaitable;
+using boost::asio::co_spawn;
+using boost::asio::detached;
+using boost::asio::use_awaitable;
+namespace this_coro = boost::asio::this_coro;
+
+awaitable<void> echo(tcp::socket socket)
+{
+ try
+ {
+ char data[1024];
+ for (;;)
+ {
+ std::size_t n = co_await socket.async_read_some(boost::asio::buffer(data), use_awaitable);
+ co_await async_write(socket, boost::asio::buffer(data, n), use_awaitable);
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::printf("echo Exception: %s\n", e.what());
+ }
+}
+
+awaitable<void> listener()
+{
+ auto executor = co_await this_coro::executor;
+ tcp::acceptor acceptor(executor, {tcp::v4(), 55555});
+ for (;;)
+ {
+ tcp::socket socket = co_await acceptor.async_accept(use_awaitable);
+ co_spawn(executor,
+ [socket = std::move(socket)]() mutable
+ {
+ return echo(std::move(socket));
+ },
+ detached);
+ }
+}
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context(1);
+
+ boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
+ signals.async_wait([&](auto, auto){ io_context.stop(); });
+
+ co_spawn(io_context, listener, detached);
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::printf("Exception: %s\n", e.what());
+ }
+}
diff --git a/src/boost/libs/asio/example/cpp17/coroutines_ts/echo_server_with_default.cpp b/src/boost/libs/asio/example/cpp17/coroutines_ts/echo_server_with_default.cpp
new file mode 100644
index 000000000..a34f8bf57
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp17/coroutines_ts/echo_server_with_default.cpp
@@ -0,0 +1,78 @@
+//
+// echo_server_with_default.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/co_spawn.hpp>
+#include <boost/asio/detached.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdio>
+
+using boost::asio::ip::tcp;
+using boost::asio::awaitable;
+using boost::asio::co_spawn;
+using boost::asio::detached;
+using boost::asio::use_awaitable_t;
+using tcp_acceptor = use_awaitable_t<>::as_default_on_t<tcp::acceptor>;
+using tcp_socket = use_awaitable_t<>::as_default_on_t<tcp::socket>;
+namespace this_coro = boost::asio::this_coro;
+
+awaitable<void> echo(tcp_socket socket)
+{
+ try
+ {
+ char data[1024];
+ for (;;)
+ {
+ std::size_t n = co_await socket.async_read_some(boost::asio::buffer(data));
+ co_await async_write(socket, boost::asio::buffer(data, n));
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::printf("echo Exception: %s\n", e.what());
+ }
+}
+
+awaitable<void> listener()
+{
+ auto executor = co_await this_coro::executor;
+ tcp_acceptor acceptor(executor, {tcp::v4(), 55555});
+ for (;;)
+ {
+ auto socket = co_await acceptor.async_accept();
+ co_spawn(executor,
+ [socket = std::move(socket)]() mutable
+ {
+ return echo(std::move(socket));
+ },
+ detached);
+ }
+}
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context(1);
+
+ boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
+ signals.async_wait([&](auto, auto){ io_context.stop(); });
+
+ co_spawn(io_context, listener, detached);
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::printf("Exception: %s\n", e.what());
+ }
+}
diff --git a/src/boost/libs/asio/example/cpp17/coroutines_ts/range_based_for.cpp b/src/boost/libs/asio/example/cpp17/coroutines_ts/range_based_for.cpp
new file mode 100644
index 000000000..477349aee
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp17/coroutines_ts/range_based_for.cpp
@@ -0,0 +1,107 @@
+//
+// range_based_for.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/co_spawn.hpp>
+#include <boost/asio/detached.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdio>
+
+using boost::asio::ip::tcp;
+using boost::asio::awaitable;
+using boost::asio::co_spawn;
+using boost::asio::detached;
+using boost::asio::use_awaitable;
+
+class connection_iter
+{
+ friend class connections;
+ tcp::acceptor* acceptor_ = nullptr;
+ tcp::socket socket_;
+
+ connection_iter(tcp::acceptor& a, tcp::socket s)
+ : acceptor_(&a), socket_(std::move(s)) {}
+
+public:
+ tcp::socket operator*()
+ {
+ return std::move(socket_);
+ }
+
+ awaitable<void> operator++()
+ {
+ socket_ = co_await acceptor_->async_accept(use_awaitable);
+ }
+
+ bool operator==(const connection_iter&) const noexcept
+ {
+ return false;
+ }
+
+ bool operator!=(const connection_iter&) const noexcept
+ {
+ return true;
+ }
+};
+
+class connections
+{
+ tcp::acceptor& acceptor_;
+
+public:
+ explicit connections(tcp::acceptor& a) : acceptor_(a) {}
+
+ awaitable<connection_iter> begin()
+ {
+ tcp::socket s = co_await acceptor_.async_accept(use_awaitable);
+ co_return connection_iter(acceptor_, std::move(s));
+ }
+
+ connection_iter end()
+ {
+ return connection_iter(acceptor_,
+ tcp::socket(acceptor_.get_executor()));
+ }
+};
+
+awaitable<void> listener(tcp::acceptor acceptor)
+{
+ for co_await (tcp::socket s : connections(acceptor))
+ {
+ co_await boost::asio::async_write(s, boost::asio::buffer("hello\r\n", 7), use_awaitable);
+ }
+}
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context(1);
+
+ boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
+ signals.async_wait([&](auto, auto){ io_context.stop(); });
+
+ tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
+ co_spawn(io_context,
+ [acceptor = std::move(acceptor)]() mutable
+ {
+ return listener(std::move(acceptor));
+ },
+ detached);
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::printf("Exception: %s\n", e.what());
+ }
+}
diff --git a/src/boost/libs/asio/example/cpp17/coroutines_ts/refactored_echo_server.cpp b/src/boost/libs/asio/example/cpp17/coroutines_ts/refactored_echo_server.cpp
new file mode 100644
index 000000000..062efc16c
--- /dev/null
+++ b/src/boost/libs/asio/example/cpp17/coroutines_ts/refactored_echo_server.cpp
@@ -0,0 +1,85 @@
+//
+// refactored_echo_server.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/co_spawn.hpp>
+#include <boost/asio/detached.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/write.hpp>
+#include <cstdio>
+
+using boost::asio::ip::tcp;
+using boost::asio::awaitable;
+using boost::asio::co_spawn;
+using boost::asio::detached;
+using boost::asio::use_awaitable;
+namespace this_coro = boost::asio::this_coro;
+
+awaitable<void> echo_once(tcp::socket& socket)
+{
+ char data[128];
+ std::size_t n = co_await socket.async_read_some(boost::asio::buffer(data), use_awaitable);
+ co_await async_write(socket, boost::asio::buffer(data, n), use_awaitable);
+}
+
+awaitable<void> echo(tcp::socket socket)
+{
+ try
+ {
+ for (;;)
+ {
+ // The asynchronous operations to echo a single chunk of data have been
+ // refactored into a separate function. When this function is called, the
+ // operations are still performed in the context of the current
+ // coroutine, and the behaviour is functionally equivalent.
+ co_await echo_once(socket);
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::printf("echo Exception: %s\n", e.what());
+ }
+}
+
+awaitable<void> listener()
+{
+ auto executor = co_await this_coro::executor;
+ tcp::acceptor acceptor(executor, {tcp::v4(), 55555});
+ for (;;)
+ {
+ tcp::socket socket = co_await acceptor.async_accept(use_awaitable);
+ co_spawn(executor,
+ [socket = std::move(socket)]() mutable
+ {
+ return echo(std::move(socket));
+ },
+ detached);
+ }
+}
+
+int main()
+{
+ try
+ {
+ boost::asio::io_context io_context(1);
+
+ boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
+ signals.async_wait([&](auto, auto){ io_context.stop(); });
+
+ co_spawn(io_context, listener, detached);
+
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::printf("Exception: %s\n", e.what());
+ }
+}
diff --git a/src/boost/libs/asio/index.html b/src/boost/libs/asio/index.html
new file mode 100644
index 000000000..a63ccdabe
--- /dev/null
+++ b/src/boost/libs/asio/index.html
@@ -0,0 +1,21 @@
+<html>
+ <head>
+ <title>Boost.Asio</title>
+ <meta http-equiv="refresh" content="0; URL=../../doc/html/boost_asio.html"/>
+ </head>
+ <body>
+ <p>
+ Automatic redirection failed, please go to
+ <a href="../../doc/html/boost_asio.html">../../doc/html/boost_asio.html</a>
+ </p>
+ <hr/>
+ <p>
+ Copyright (c) 2008 Christopher M. Kohlhoff
+ </p>
+ <p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
+ <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+ </body>
+</html>
diff --git a/src/boost/libs/asio/meta/libraries.json b/src/boost/libs/asio/meta/libraries.json
new file mode 100644
index 000000000..685753d08
--- /dev/null
+++ b/src/boost/libs/asio/meta/libraries.json
@@ -0,0 +1,15 @@
+{
+ "key": "asio",
+ "name": "Asio",
+ "authors": [
+ "Chris Kohlhoff"
+ ],
+ "description": "Portable networking and other low-level I/O, including sockets, timers, hostname resolution, socket iostreams, serial ports, file descriptors and Windows HANDLEs.",
+ "category": [
+ "Concurrent",
+ "IO"
+ ],
+ "maintainers": [
+ "Chris Kohlhoff <chris -at- kohlhoff.com>"
+ ]
+}
diff --git a/src/boost/libs/asio/test/Jamfile.v2 b/src/boost/libs/asio/test/Jamfile.v2
new file mode 100644
index 000000000..a9835751c
--- /dev/null
+++ b/src/boost/libs/asio/test/Jamfile.v2
@@ -0,0 +1,235 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+import feature ;
+
+lib socket ; # SOLARIS, QNXNTO
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+local USE_SELECT =
+ <define>BOOST_ASIO_DISABLE_DEV_POLL
+ <define>BOOST_ASIO_DISABLE_EPOLL
+ <define>BOOST_ASIO_DISABLE_KQUEUE
+ <define>BOOST_ASIO_DISABLE_IOCP
+ ;
+
+project
+ : requirements
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <library>/boost/regex//boost_regex
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>linux:<define>_XOPEN_SOURCE=600
+ <target-os>linux:<define>_GNU_SOURCE=1
+ <target-os>solaris:<define>_XOPEN_SOURCE=500
+ <target-os>solaris:<define>__EXTENSIONS__
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>cw:<library>ws2_32
+ <target-os>windows,<toolset>cw:<library>mswsock
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>qnxnto:<library>socket
+ <target-os>haiku:<library>network
+ ;
+
+test-suite "asio" :
+ [ link awaitable.cpp ]
+ [ link awaitable.cpp : $(USE_SELECT) : awaitable_select ]
+ [ link basic_datagram_socket.cpp ]
+ [ link basic_datagram_socket.cpp : $(USE_SELECT) : basic_datagram_socket_select ]
+ [ link basic_deadline_timer.cpp ]
+ [ link basic_deadline_timer.cpp : $(USE_SELECT) : basic_deadline_timer_select ]
+ [ link basic_raw_socket.cpp ]
+ [ link basic_raw_socket.cpp : $(USE_SELECT) : basic_raw_socket_select ]
+ [ link basic_seq_packet_socket.cpp ]
+ [ link basic_seq_packet_socket.cpp : $(USE_SELECT) : basic_seq_packet_socket_select ]
+ [ link basic_signal_set.cpp ]
+ [ link basic_signal_set.cpp : $(USE_SELECT) : basic_signal_set_select ]
+ [ link basic_socket_acceptor.cpp ]
+ [ link basic_socket_acceptor.cpp : $(USE_SELECT) : basic_socket_acceptor_select ]
+ [ link basic_stream_socket.cpp ]
+ [ link basic_stream_socket.cpp : $(USE_SELECT) : basic_stream_socket_select ]
+ [ link basic_streambuf.cpp ]
+ [ link basic_streambuf.cpp : $(USE_SELECT) : basic_streambuf_select ]
+ [ link basic_waitable_timer.cpp ]
+ [ link basic_waitable_timer.cpp : $(USE_SELECT) : basic_waitable_timer_select ]
+ [ run buffer.cpp ]
+ [ run buffer.cpp : : : $(USE_SELECT) : buffer_select ]
+ [ run buffered_read_stream.cpp ]
+ [ run buffered_read_stream.cpp : : : $(USE_SELECT) : buffered_read_stream_select ]
+ [ run buffered_stream.cpp ]
+ [ run buffered_stream.cpp : : : $(USE_SELECT) : buffered_stream_select ]
+ [ run buffered_write_stream.cpp ]
+ [ run buffered_write_stream.cpp : : : $(USE_SELECT) : buffered_write_stream_select ]
+ [ run buffers_iterator.cpp ]
+ [ run buffers_iterator.cpp : : : $(USE_SELECT) : buffers_iterator_select ]
+ [ link co_spawn.cpp ]
+ [ link co_spawn.cpp : $(USE_SELECT) : co_spawn_select ]
+ [ link completion_condition.cpp ]
+ [ link completion_condition.cpp : $(USE_SELECT) : completion_condition_select ]
+ [ run compose.cpp ]
+ [ run compose.cpp : : : $(USE_SELECT) : compose_select ]
+ [ link connect.cpp ]
+ [ link connect.cpp : $(USE_SELECT) : connect_select ]
+ [ link coroutine.cpp ]
+ [ link coroutine.cpp : $(USE_SELECT) : coroutine_select ]
+ [ run deadline_timer.cpp ]
+ [ run deadline_timer.cpp : : : $(USE_SELECT) : deadline_timer_select ]
+ [ link detached.cpp ]
+ [ link detached.cpp : $(USE_SELECT) : detached_select ]
+ [ run error.cpp ]
+ [ run error.cpp : : : $(USE_SELECT) : error_select ]
+ [ link generic/basic_endpoint.cpp : : generic_basic_endpoint ]
+ [ link generic/basic_endpoint.cpp : $(USE_SELECT) : generic_basic_endpoint_select ]
+ [ link generic/datagram_protocol.cpp : : generic_datagram_protocol ]
+ [ link generic/datagram_protocol.cpp : $(USE_SELECT) : generic_datagram_protocol_select ]
+ [ link generic/raw_protocol.cpp : : generic_raw_protocol ]
+ [ link generic/raw_protocol.cpp : $(USE_SELECT) : generic_raw_protocol_select ]
+ [ link generic/seq_packet_protocol.cpp : : generic_seq_packet_protocol ]
+ [ link generic/seq_packet_protocol.cpp : $(USE_SELECT) : generic_seq_packet_protocol_select ]
+ [ link generic/stream_protocol.cpp : : generic_stream_protocol ]
+ [ link generic/stream_protocol.cpp : $(USE_SELECT) : generic_stream_protocol_select ]
+ [ link high_resolution_timer.cpp ]
+ [ link high_resolution_timer.cpp : $(USE_SELECT) : high_resolution_timer_select ]
+ [ run io_context.cpp ]
+ [ run io_context.cpp : : : $(USE_SELECT) : io_context_select ]
+ [ run io_context_strand.cpp ]
+ [ run io_context_strand.cpp : : : $(USE_SELECT) : io_context_strand_select ]
+ [ link ip/address.cpp : : ip_address ]
+ [ link ip/address.cpp : $(USE_SELECT) : ip_address_select ]
+ [ link ip/address_v4.cpp : : ip_address_v4 ]
+ [ link ip/address_v4.cpp : $(USE_SELECT) : ip_address_v4_select ]
+ [ link ip/address_v6.cpp : : ip_address_v6 ]
+ [ link ip/address_v6.cpp : $(USE_SELECT) : ip_address_v6_select ]
+ [ link ip/basic_endpoint.cpp : : ip_basic_endpoint ]
+ [ link ip/basic_endpoint.cpp : $(USE_SELECT) : ip_basic_endpoint_select ]
+ [ link ip/basic_resolver.cpp : : ip_basic_resolver ]
+ [ link ip/basic_resolver.cpp : $(USE_SELECT) : ip_basic_resolver_select ]
+ [ link ip/basic_resolver_entry.cpp : : ip_basic_resolver_entry ]
+ [ link ip/basic_resolver_entry.cpp : $(USE_SELECT) : ip_basic_resolver_entry_select ]
+ [ link ip/basic_resolver_iterator.cpp : : ip_basic_resolver_iterator ]
+ [ link ip/basic_resolver_iterator.cpp : $(USE_SELECT) : ip_basic_resolver_iterator_select ]
+ [ link ip/basic_resolver_query.cpp : : ip_basic_resolver_query ]
+ [ link ip/basic_resolver_query.cpp : $(USE_SELECT) : ip_basic_resolver_query_select ]
+ [ run ip/host_name.cpp : : : : ip_host_name ]
+ [ run ip/host_name.cpp : : : $(USE_SELECT) : ip_host_name_select ]
+ [ run ip/icmp.cpp : : : : ip_icmp ]
+ [ run ip/icmp.cpp : : : $(USE_SELECT) : ip_icmp_select ]
+ [ run ip/multicast.cpp : : : : ip_multicast ]
+ [ run ip/multicast.cpp : : : $(USE_SELECT) : ip_multicast_select ]
+ [ link ip/resolver_query_base.cpp : : ip_resolver_query_base ]
+ [ link ip/resolver_query_base.cpp : $(USE_SELECT) : ip_resolver_query_base_select ]
+ [ run ip/tcp.cpp : : : : ip_tcp ]
+ [ run ip/tcp.cpp : : : $(USE_SELECT) : ip_tcp_select ]
+ [ run ip/udp.cpp : : : : ip_udp ]
+ [ run ip/udp.cpp : : : $(USE_SELECT) : ip_udp_select ]
+ [ run ip/unicast.cpp : : : : ip_unicast ]
+ [ run ip/unicast.cpp : : : $(USE_SELECT) : ip_unicast_select ]
+ [ run ip/v6_only.cpp : : : : ip_v6_only ]
+ [ run ip/v6_only.cpp : : : $(USE_SELECT) : ip_v6_only_select ]
+ [ run is_read_buffered.cpp ]
+ [ run is_read_buffered.cpp : : : $(USE_SELECT) : is_read_buffered_select ]
+ [ run is_write_buffered.cpp ]
+ [ run is_write_buffered.cpp : : : $(USE_SELECT) : is_write_buffered_select ]
+ [ link local/basic_endpoint.cpp : : local_basic_endpoint ]
+ [ link local/basic_endpoint.cpp : $(USE_SELECT) : local_basic_endpoint_select ]
+ [ link local/connect_pair.cpp : : local_connect_pair ]
+ [ link local/connect_pair.cpp : $(USE_SELECT) : local_connect_pair_select ]
+ [ link local/datagram_protocol.cpp : : local_datagram_protocol ]
+ [ link local/datagram_protocol.cpp : $(USE_SELECT) : local_datagram_protocol_select ]
+ [ link local/stream_protocol.cpp : : local_stream_protocol ]
+ [ link local/stream_protocol.cpp : $(USE_SELECT) : local_stream_protocol_select ]
+ [ link placeholders.cpp ]
+ [ link placeholders.cpp : $(USE_SELECT) : placeholders_select ]
+ [ link posix/basic_descriptor.cpp : : posix_basic_descriptor ]
+ [ link posix/basic_descriptor.cpp : $(USE_SELECT) : posix_basic_descriptor_select ]
+ [ link posix/basic_stream_descriptor.cpp : : posix_basic_stream_descriptor ]
+ [ link posix/basic_stream_descriptor.cpp : $(USE_SELECT) : posix_basic_stream_descriptor_select ]
+ [ link posix/descriptor_base.cpp : : posix_descriptor_base ]
+ [ link posix/descriptor_base.cpp : $(USE_SELECT) : posix_descriptor_base_select ]
+ [ link posix/stream_descriptor.cpp : : posix_stream_descriptor ]
+ [ link posix/stream_descriptor.cpp : $(USE_SELECT) : posix_stream_descriptor_select ]
+ [ run read.cpp ]
+ [ run read.cpp : : : $(USE_SELECT) : read_select ]
+ [ run read_at.cpp ]
+ [ run read_at.cpp : : : $(USE_SELECT) : read_at_select ]
+ [ run read_until.cpp ]
+ [ run read_until.cpp : : : $(USE_SELECT) : read_until_select ]
+ [ link redirect_error.cpp ]
+ [ link redirect_error.cpp : $(USE_SELECT) : redirect_error_select ]
+ [ run signal_set.cpp ]
+ [ run signal_set.cpp : : : $(USE_SELECT) : signal_set_select ]
+ [ run socket_base.cpp ]
+ [ run socket_base.cpp : : : $(USE_SELECT) : socket_base_select ]
+ [ link steady_timer.cpp ]
+ [ link steady_timer.cpp : $(USE_SELECT) : steady_timer_select ]
+ [ run strand.cpp ]
+ [ run strand.cpp : : : $(USE_SELECT) : strand_select ]
+ [ run streambuf.cpp ]
+ [ run streambuf.cpp : : : $(USE_SELECT) : streambuf_select ]
+ [ link system_timer.cpp ]
+ [ link system_timer.cpp : $(USE_SELECT) : system_timer_select ]
+ [ link system_context.cpp ]
+ [ link system_context.cpp : $(USE_SELECT) : system_context_select ]
+ [ link system_executor.cpp ]
+ [ link system_executor.cpp : $(USE_SELECT) : system_executor_select ]
+ [ link this_coro.cpp ]
+ [ link this_coro.cpp : $(USE_SELECT) : this_coro_select ]
+ [ link time_traits.cpp ]
+ [ link time_traits.cpp : $(USE_SELECT) : time_traits_select ]
+ [ link ts/buffer.cpp : : ts_buffer ]
+ [ link ts/buffer.cpp : $(USE_SELECT) : ts_buffer_select ]
+ [ link ts/executor.cpp : : ts_executor ]
+ [ link ts/executor.cpp : $(USE_SELECT) : ts_executor_select ]
+ [ link ts/internet.cpp : : ts_internet ]
+ [ link ts/internet.cpp : $(USE_SELECT) : ts_internet_select ]
+ [ link ts/io_context.cpp : : ts_io_context ]
+ [ link ts/io_context.cpp : $(USE_SELECT) : ts_io_context_select ]
+ [ link ts/net.cpp : : ts_net ]
+ [ link ts/net.cpp : $(USE_SELECT) : ts_net_select ]
+ [ link ts/netfwd.cpp : : ts_netfwd ]
+ [ link ts/netfwd.cpp : $(USE_SELECT) : ts_netfwd_select ]
+ [ link ts/socket.cpp : : ts_socket ]
+ [ link ts/socket.cpp : $(USE_SELECT) : ts_socket_select ]
+ [ link ts/timer.cpp : : ts_timer ]
+ [ link ts/timer.cpp : $(USE_SELECT) : ts_timer_select ]
+ [ link use_awaitable.cpp ]
+ [ link use_awaitable.cpp : $(USE_SELECT) : use_awaitable_select ]
+ [ link wait_traits.cpp ]
+ [ link wait_traits.cpp : $(USE_SELECT) : wait_traits_select ]
+ [ link windows/basic_object_handle.cpp : : windows_basic_object_handle ]
+ [ link windows/basic_object_handle.cpp : $(USE_SELECT) : windows_basic_object_handle_select ]
+ [ link windows/basic_overlapped_handle.cpp : : windows_basic_overlapped_handle ]
+ [ link windows/basic_overlapped_handle.cpp : $(USE_SELECT) : windows_basic_overlapped_handle_select ]
+ [ link windows/basic_random_access_handle.cpp : : windows_basic_random_access_handle ]
+ [ link windows/basic_random_access_handle.cpp : $(USE_SELECT) : windows_basic_random_access_handle_select ]
+ [ link windows/basic_stream_handle.cpp : : windows_basic_stream_handle ]
+ [ link windows/basic_stream_handle.cpp : $(USE_SELECT) : windows_basic_stream_handle_select ]
+ [ link windows/object_handle.cpp : : windows_object_handle ]
+ [ link windows/object_handle.cpp : $(USE_SELECT) : windows_object_handle_select ]
+ [ link windows/overlapped_ptr.cpp : : windows_overlapped_ptr ]
+ [ link windows/overlapped_ptr.cpp : $(USE_SELECT) : windows_overlapped_ptr_select ]
+ [ link windows/random_access_handle.cpp : : windows_random_access_handle ]
+ [ link windows/random_access_handle.cpp : $(USE_SELECT) : windows_random_access_handle_select ]
+ [ link windows/stream_handle.cpp : : windows_stream_handle ]
+ [ link windows/stream_handle.cpp : $(USE_SELECT) : windows_stream_handle_select ]
+ [ run write.cpp ]
+ [ run write.cpp : : : $(USE_SELECT) : write_select ]
+ [ run write_at.cpp ]
+ [ run write_at.cpp : : : $(USE_SELECT) : write_at_select ]
+ ;
diff --git a/src/boost/libs/asio/test/archetypes/async_ops.hpp b/src/boost/libs/asio/test/archetypes/async_ops.hpp
new file mode 100644
index 000000000..99a33b28d
--- /dev/null
+++ b/src/boost/libs/asio/test/archetypes/async_ops.hpp
@@ -0,0 +1,415 @@
+//
+// async_ops.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 ARCHETYPES_ASYNC_OPS_HPP
+#define ARCHETYPES_ASYNC_OPS_HPP
+
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/error.hpp>
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+namespace archetypes {
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void())
+async_op_0(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void()>::completion_handler_type handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void()> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ ex.post(BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler), a);
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::system::error_code))
+async_op_ec_0(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(boost::system::error_code)>::completion_handler_type handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(boost::system::error_code)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ if (ok)
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ boost::system::error_code()), a);
+ }
+ else
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ boost::system::error_code(boost::asio::error::operation_aborted)), a);
+ }
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(std::exception_ptr))
+async_op_ex_0(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(std::exception_ptr)>::completion_handler_type handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(std::exception_ptr)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ if (ok)
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ std::exception_ptr()), a);
+ }
+ else
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ std::make_exception_ptr(std::runtime_error("blah"))), a);
+ }
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int))
+async_op_1(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(int)>::completion_handler_type handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(int)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ 42), a);
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
+ void(boost::system::error_code, int))
+async_op_ec_1(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(boost::system::error_code, int)>::completion_handler_type
+ handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(boost::system::error_code, int)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ if (ok)
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ boost::system::error_code(), 42), a);
+ }
+ else
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ boost::system::error_code(boost::asio::error::operation_aborted),
+ 0), a);
+ }
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(std::exception_ptr, int))
+async_op_ex_1(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(std::exception_ptr, int)>::completion_handler_type
+ handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(std::exception_ptr, int)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ if (ok)
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ std::exception_ptr(), 42), a);
+ }
+ else
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ std::make_exception_ptr(std::runtime_error("blah")), 0), a);
+ }
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int, double))
+async_op_2(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(int, double)>::completion_handler_type handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(int, double)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ 42, 2.0), a);
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
+ void(boost::system::error_code, int, double))
+async_op_ec_2(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(boost::system::error_code, int, double)>::completion_handler_type
+ handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(boost::system::error_code, int, double)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ if (ok)
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ boost::system::error_code(), 42, 2.0), a);
+ }
+ else
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ boost::system::error_code(boost::asio::error::operation_aborted),
+ 0, 0.0), a);
+ }
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
+ void(std::exception_ptr, int, double))
+async_op_ex_2(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(std::exception_ptr, int, double)>::completion_handler_type
+ handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(std::exception_ptr, int, double)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ if (ok)
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ std::exception_ptr(), 42, 2.0), a);
+ }
+ else
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ std::make_exception_ptr(std::runtime_error("blah")), 0, 0.0), a);
+ }
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int, double, char))
+async_op_3(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(int, double, char)>::completion_handler_type handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(int, double, char)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ 42, 2.0, 'a'), a);
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
+ void(boost::system::error_code, int, double, char))
+async_op_ec_3(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(boost::system::error_code, int, double, char)>::completion_handler_type
+ handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(boost::system::error_code, int, double, char)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ if (ok)
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ boost::system::error_code(), 42, 2.0, 'a'), a);
+ }
+ else
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ boost::system::error_code(boost::asio::error::operation_aborted),
+ 0, 0.0, 'z'), a);
+ }
+
+ return completion.result.get();
+}
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
+ void(std::exception_ptr, int, double, char))
+async_op_ex_3(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef typename boost::asio::async_completion<CompletionToken,
+ void(std::exception_ptr, int, double, char)>::completion_handler_type
+ handler_type;
+
+ boost::asio::async_completion<CompletionToken,
+ void(std::exception_ptr, int, double, char)> completion(token);
+
+ typename boost::asio::associated_allocator<handler_type>::type a
+ = boost::asio::get_associated_allocator(completion.completion_handler);
+
+ typename boost::asio::associated_executor<handler_type>::type ex
+ = boost::asio::get_associated_executor(completion.completion_handler);
+
+ if (ok)
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ std::exception_ptr(), 42, 2.0, 'a'), a);
+ }
+ else
+ {
+ ex.post(
+ bindns::bind(
+ BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
+ std::make_exception_ptr(std::runtime_error("blah")),
+ 0, 0.0, 'z'), a);
+ }
+
+ return completion.result.get();
+}
+
+} // namespace archetypes
+
+#endif // ARCHETYPES_ASYNC_OPS_HPP
diff --git a/src/boost/libs/asio/test/archetypes/async_result.hpp b/src/boost/libs/asio/test/archetypes/async_result.hpp
new file mode 100644
index 000000000..50193eca3
--- /dev/null
+++ b/src/boost/libs/asio/test/archetypes/async_result.hpp
@@ -0,0 +1,96 @@
+//
+// async_result.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 ARCHETYPES_ASYNC_RESULT_HPP
+#define ARCHETYPES_ASYNC_RESULT_HPP
+
+#include <boost/asio/async_result.hpp>
+
+namespace archetypes {
+
+struct lazy_handler
+{
+};
+
+template <typename Signature>
+struct concrete_handler;
+
+template <typename R, typename Arg1>
+struct concrete_handler<R(Arg1)>
+{
+ concrete_handler(lazy_handler)
+ {
+ }
+
+ void operator()(typename boost::asio::decay<Arg1>::type)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ concrete_handler(concrete_handler&&) {}
+private:
+ concrete_handler(const concrete_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+template <typename R, typename Arg1, typename Arg2>
+struct concrete_handler<R(Arg1, Arg2)>
+{
+ concrete_handler(lazy_handler)
+ {
+ }
+
+ void operator()(typename boost::asio::decay<Arg1>::type, typename boost::asio::decay<Arg2>::type)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ concrete_handler(concrete_handler&&) {}
+private:
+ concrete_handler(const concrete_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+} // namespace archetypes
+
+namespace boost {
+namespace asio {
+
+template <typename Signature>
+class async_result<archetypes::lazy_handler, Signature>
+{
+public:
+ // The concrete completion handler type.
+ typedef archetypes::concrete_handler<Signature> completion_handler_type;
+
+ // The return type of the initiating function.
+ typedef int return_type;
+
+ // Construct an async_result from a given handler.
+ explicit async_result(completion_handler_type&)
+ {
+ }
+
+ // Obtain the value to be returned from the initiating function.
+ return_type get()
+ {
+ return 42;
+ }
+
+private:
+ // Disallow copying and assignment.
+ async_result(const async_result&) BOOST_ASIO_DELETED;
+ async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
+};
+
+} // namespace asio
+} // namespace boost
+
+#endif // ARCHETYPES_ASYNC_RESULT_HPP
diff --git a/src/boost/libs/asio/test/archetypes/gettable_socket_option.hpp b/src/boost/libs/asio/test/archetypes/gettable_socket_option.hpp
new file mode 100644
index 000000000..29a75753b
--- /dev/null
+++ b/src/boost/libs/asio/test/archetypes/gettable_socket_option.hpp
@@ -0,0 +1,54 @@
+//
+// gettable_socket_option.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 ARCHETYPES_GETTABLE_SOCKET_OPTION_HPP
+#define ARCHETYPES_GETTABLE_SOCKET_OPTION_HPP
+
+#include <cstddef>
+
+namespace archetypes {
+
+template <typename PointerType>
+class gettable_socket_option
+{
+public:
+ template <typename Protocol>
+ int level(const Protocol&) const
+ {
+ return 0;
+ }
+
+ template <typename Protocol>
+ int name(const Protocol&) const
+ {
+ return 0;
+ }
+
+ template <typename Protocol>
+ PointerType* data(const Protocol&)
+ {
+ return 0;
+ }
+
+ template <typename Protocol>
+ std::size_t size(const Protocol&) const
+ {
+ return 0;
+ }
+
+ template <typename Protocol>
+ void resize(const Protocol&, std::size_t)
+ {
+ }
+};
+
+} // namespace archetypes
+
+#endif // ARCHETYPES_GETTABLE_SOCKET_OPTION_HPP
diff --git a/src/boost/libs/asio/test/archetypes/io_control_command.hpp b/src/boost/libs/asio/test/archetypes/io_control_command.hpp
new file mode 100644
index 000000000..d0c329360
--- /dev/null
+++ b/src/boost/libs/asio/test/archetypes/io_control_command.hpp
@@ -0,0 +1,32 @@
+//
+// io_control_command.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 ARCHETYPES_IO_CONTROL_COMMAND_HPP
+#define ARCHETYPES_IO_CONTROL_COMMAND_HPP
+
+namespace archetypes {
+
+class io_control_command
+{
+public:
+ int name() const
+ {
+ return 0;
+ }
+
+ void* data()
+ {
+ return 0;
+ }
+};
+
+} // namespace archetypes
+
+#endif // ARCHETYPES_IO_CONTROL_COMMAND_HPP
diff --git a/src/boost/libs/asio/test/archetypes/settable_socket_option.hpp b/src/boost/libs/asio/test/archetypes/settable_socket_option.hpp
new file mode 100644
index 000000000..01eeb0d94
--- /dev/null
+++ b/src/boost/libs/asio/test/archetypes/settable_socket_option.hpp
@@ -0,0 +1,49 @@
+//
+// settable_socket_option.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 ARCHETYPES_SETTABLE_SOCKET_OPTION_HPP
+#define ARCHETYPES_SETTABLE_SOCKET_OPTION_HPP
+
+#include <cstddef>
+
+namespace archetypes {
+
+template <typename PointerType>
+class settable_socket_option
+{
+public:
+ template <typename Protocol>
+ int level(const Protocol&) const
+ {
+ return 0;
+ }
+
+ template <typename Protocol>
+ int name(const Protocol&) const
+ {
+ return 0;
+ }
+
+ template <typename Protocol>
+ const PointerType* data(const Protocol&) const
+ {
+ return 0;
+ }
+
+ template <typename Protocol>
+ std::size_t size(const Protocol&) const
+ {
+ return 0;
+ }
+};
+
+} // namespace archetypes
+
+#endif // ARCHETYPES_SETTABLE_SOCKET_OPTION_HPP
diff --git a/src/boost/libs/asio/test/associated_allocator.cpp b/src/boost/libs/asio/test/associated_allocator.cpp
new file mode 100644
index 000000000..5a4471e13
--- /dev/null
+++ b/src/boost/libs/asio/test/associated_allocator.cpp
@@ -0,0 +1,25 @@
+//
+// associated_allocator.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/associated_allocator.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "associated_allocator",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/associated_executor.cpp b/src/boost/libs/asio/test/associated_executor.cpp
new file mode 100644
index 000000000..b26a450ed
--- /dev/null
+++ b/src/boost/libs/asio/test/associated_executor.cpp
@@ -0,0 +1,25 @@
+//
+// associated_executor.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/associated_executor.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "associated_executor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/async_result.cpp b/src/boost/libs/asio/test/async_result.cpp
new file mode 100644
index 000000000..8df819d53
--- /dev/null
+++ b/src/boost/libs/asio/test/async_result.cpp
@@ -0,0 +1,25 @@
+//
+// async_result.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/async_result.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "async_result",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/awaitable.cpp b/src/boost/libs/asio/test/awaitable.cpp
new file mode 100644
index 000000000..6730bce8a
--- /dev/null
+++ b/src/boost/libs/asio/test/awaitable.cpp
@@ -0,0 +1,25 @@
+//
+// awaitable.cpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/awaitable.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "awaitable",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_datagram_socket.cpp b/src/boost/libs/asio/test/basic_datagram_socket.cpp
new file mode 100644
index 000000000..f21788543
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_datagram_socket.cpp
@@ -0,0 +1,25 @@
+//
+// basic_datagram_socket.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_datagram_socket.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_datagram_socket",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_deadline_timer.cpp b/src/boost/libs/asio/test/basic_deadline_timer.cpp
new file mode 100644
index 000000000..ac5e43e97
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_deadline_timer.cpp
@@ -0,0 +1,25 @@
+//
+// basic_deadline_timer.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_deadline_timer.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_deadline_timer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_raw_socket.cpp b/src/boost/libs/asio/test/basic_raw_socket.cpp
new file mode 100644
index 000000000..e93d27c3d
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_raw_socket.cpp
@@ -0,0 +1,25 @@
+//
+// basic_raw_socket.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_raw_socket.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_raw_socket",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_seq_packet_socket.cpp b/src/boost/libs/asio/test/basic_seq_packet_socket.cpp
new file mode 100644
index 000000000..27268b360
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_seq_packet_socket.cpp
@@ -0,0 +1,25 @@
+//
+// basic_seq_packet_socket.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_seq_packet_socket.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_seq_packet_socket",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_serial_port.cpp b/src/boost/libs/asio/test/basic_serial_port.cpp
new file mode 100644
index 000000000..f5055317a
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_serial_port.cpp
@@ -0,0 +1,26 @@
+//
+// basic_serial_port.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_serial_port.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_serial_port",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_signal_set.cpp b/src/boost/libs/asio/test/basic_signal_set.cpp
new file mode 100644
index 000000000..d699b07f9
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_signal_set.cpp
@@ -0,0 +1,25 @@
+//
+// basic_signal_set.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_signal_set.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_signal_set",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_socket.cpp b/src/boost/libs/asio/test/basic_socket.cpp
new file mode 100644
index 000000000..9b4d13746
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_socket.cpp
@@ -0,0 +1,25 @@
+//
+// basic_socket.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_socket.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_socket",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_socket_acceptor.cpp b/src/boost/libs/asio/test/basic_socket_acceptor.cpp
new file mode 100644
index 000000000..aa6e4c113
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_socket_acceptor.cpp
@@ -0,0 +1,25 @@
+//
+// basic_socket_acceptor.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_socket_acceptor.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_socket_acceptor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_stream_socket.cpp b/src/boost/libs/asio/test/basic_stream_socket.cpp
new file mode 100644
index 000000000..01195d315
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_stream_socket.cpp
@@ -0,0 +1,25 @@
+//
+// basic_stream_socket.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_stream_socket.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_stream_socket",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_streambuf.cpp b/src/boost/libs/asio/test/basic_streambuf.cpp
new file mode 100644
index 000000000..e9d6139cd
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_streambuf.cpp
@@ -0,0 +1,25 @@
+//
+// basic_streambuf.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_streambuf.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_streambuf",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/basic_waitable_timer.cpp b/src/boost/libs/asio/test/basic_waitable_timer.cpp
new file mode 100644
index 000000000..2321747c9
--- /dev/null
+++ b/src/boost/libs/asio/test/basic_waitable_timer.cpp
@@ -0,0 +1,25 @@
+//
+// basic_waitable_timer.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/basic_waitable_timer.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_waitable_timer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/bind_executor.cpp b/src/boost/libs/asio/test/bind_executor.cpp
new file mode 100644
index 000000000..cc95310b5
--- /dev/null
+++ b/src/boost/libs/asio/test/bind_executor.cpp
@@ -0,0 +1,25 @@
+//
+// bind_executor.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/bind_executor.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "bind_executor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/buffer.cpp b/src/boost/libs/asio/test/buffer.cpp
new file mode 100644
index 000000000..806856026
--- /dev/null
+++ b/src/boost/libs/asio/test/buffer.cpp
@@ -0,0 +1,830 @@
+//
+// buffer.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/buffer.hpp>
+
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <boost/array.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+//------------------------------------------------------------------------------
+
+// buffer_compile test
+// ~~~~~~~~~~~~~~~~~~~
+// The following test checks that all overloads of the buffer function compile
+// and link correctly. Runtime failures are ignored.
+
+namespace buffer_compile {
+
+using namespace boost::asio;
+
+void test()
+{
+ try
+ {
+ char raw_data[1024];
+ const char const_raw_data[1024] = "";
+ void* void_ptr_data = raw_data;
+ const void* const_void_ptr_data = const_raw_data;
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::array<char, 1024> array_data;
+ const boost::array<char, 1024>& const_array_data_1 = array_data;
+ boost::array<const char, 1024> const_array_data_2 = { { 0 } };
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ std::array<char, 1024> std_array_data;
+ const std::array<char, 1024>& const_std_array_data_1 = std_array_data;
+ std::array<const char, 1024> const_std_array_data_2 = { { 0 } };
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+ std::vector<char> vector_data(1024);
+ const std::vector<char>& const_vector_data = vector_data;
+ std::string string_data(1024, ' ');
+ const std::string const_string_data(1024, ' ');
+ std::vector<mutable_buffer> mutable_buffer_sequence;
+ std::vector<const_buffer> const_buffer_sequence;
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ std::string_view string_view_data(string_data);
+#elif defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ std::experimental::string_view string_view_data(string_data);
+#endif // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+
+ // mutable_buffer constructors.
+
+ mutable_buffer mb1;
+ mutable_buffer mb2(void_ptr_data, 1024);
+ mutable_buffer mb3(mb1);
+ (void)mb3;
+
+ // mutable_buffer functions.
+
+ void* ptr1 = mb1.data();
+ (void)ptr1;
+
+ std::size_t n1 = mb1.size();
+ (void)n1;
+
+ // mutable_buffer operators.
+
+ mb1 += 128;
+ mb1 = mb2 + 128;
+ mb1 = 128 + mb2;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // mutable_buffers_1 constructors.
+
+ mutable_buffers_1 mbc1(mb1);
+ mutable_buffers_1 mbc2(mbc1);
+
+ // mutable_buffers_1 functions.
+
+ mutable_buffers_1::const_iterator iter1 = mbc1.begin();
+ (void)iter1;
+ mutable_buffers_1::const_iterator iter2 = mbc1.end();
+ (void)iter2;
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // const_buffer constructors.
+
+ const_buffer cb1;
+ const_buffer cb2(const_void_ptr_data, 1024);
+ const_buffer cb3(cb1);
+ (void)cb3;
+ const_buffer cb4(mb1);
+ (void)cb4;
+
+ // const_buffer functions.
+
+ const void* ptr2 = cb1.data();
+ (void)ptr2;
+
+ std::size_t n2 = cb1.size();
+ (void)n2;
+
+ // const_buffer operators.
+
+ cb1 += 128;
+ cb1 = cb2 + 128;
+ cb1 = 128 + cb2;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // const_buffers_1 constructors.
+
+ const_buffers_1 cbc1(cb1);
+ const_buffers_1 cbc2(cbc1);
+
+ // const_buffers_1 functions.
+
+ const_buffers_1::const_iterator iter3 = cbc1.begin();
+ (void)iter3;
+ const_buffers_1::const_iterator iter4 = cbc1.end();
+ (void)iter4;
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // buffer_size function overloads.
+
+ std::size_t size1 = buffer_size(mb1);
+ (void)size1;
+ std::size_t size2 = buffer_size(cb1);
+ (void)size2;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size3 = buffer_size(mbc1);
+ (void)size3;
+ std::size_t size4 = buffer_size(cbc1);
+ (void)size4;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size5 = buffer_size(mutable_buffer_sequence);
+ (void)size5;
+ std::size_t size6 = buffer_size(const_buffer_sequence);
+ (void)size6;
+
+ // buffer_cast function overloads.
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ void* ptr3 = buffer_cast<void*>(mb1);
+ (void)ptr3;
+ const void* ptr4 = buffer_cast<const void*>(cb1);
+ (void)ptr4;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // buffer function overloads.
+
+ mb1 = buffer(mb2);
+ mb1 = buffer(mb2, 128);
+ cb1 = buffer(cb2);
+ cb1 = buffer(cb2, 128);
+ mb1 = buffer(void_ptr_data, 1024);
+ cb1 = buffer(const_void_ptr_data, 1024);
+ mb1 = buffer(raw_data);
+ mb1 = buffer(raw_data, 1024);
+ cb1 = buffer(const_raw_data);
+ cb1 = buffer(const_raw_data, 1024);
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ mb1 = buffer(array_data);
+ mb1 = buffer(array_data, 1024);
+ cb1 = buffer(const_array_data_1);
+ cb1 = buffer(const_array_data_1, 1024);
+ cb1 = buffer(const_array_data_2);
+ cb1 = buffer(const_array_data_2, 1024);
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ mb1 = buffer(std_array_data);
+ mb1 = buffer(std_array_data, 1024);
+ cb1 = buffer(const_std_array_data_1);
+ cb1 = buffer(const_std_array_data_1, 1024);
+ cb1 = buffer(const_std_array_data_2);
+ cb1 = buffer(const_std_array_data_2, 1024);
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+ mb1 = buffer(vector_data);
+ mb1 = buffer(vector_data, 1024);
+ cb1 = buffer(const_vector_data);
+ cb1 = buffer(const_vector_data, 1024);
+ mb1 = buffer(string_data);
+ mb1 = buffer(string_data, 1024);
+ cb1 = buffer(const_string_data);
+ cb1 = buffer(const_string_data, 1024);
+#if defined(BOOST_ASIO_HAS_STRING_VIEW)
+ cb1 = buffer(string_view_data);
+ cb1 = buffer(string_view_data, 1024);
+#endif // defined(BOOST_ASIO_HAS_STRING_VIEW)
+
+ // buffer_copy function overloads.
+
+ std::size_t size7 = buffer_copy(mb1, cb2);
+ (void)size7;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size8 = buffer_copy(mb1, cbc2);
+ (void)size8;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size9 = buffer_copy(mb1, mb2);
+ (void)size9;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size10 = buffer_copy(mb1, mbc2);
+ (void)size10;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size11 = buffer_copy(mb1, const_buffer_sequence);
+ (void)size11;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size12 = buffer_copy(mbc1, cb2);
+ (void)size12;
+ std::size_t size13 = buffer_copy(mbc1, cbc2);
+ (void)size13;
+ std::size_t size14 = buffer_copy(mbc1, mb2);
+ (void)size14;
+ std::size_t size15 = buffer_copy(mbc1, mbc2);
+ (void)size15;
+ std::size_t size16 = buffer_copy(mbc1, const_buffer_sequence);
+ (void)size16;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size17 = buffer_copy(mutable_buffer_sequence, cb2);
+ (void)size17;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size18 = buffer_copy(mutable_buffer_sequence, cbc2);
+ (void)size18;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size19 = buffer_copy(mutable_buffer_sequence, mb2);
+ (void)size19;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size20 = buffer_copy(mutable_buffer_sequence, mbc2);
+ (void)size20;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size21 = buffer_copy(
+ mutable_buffer_sequence, const_buffer_sequence);
+ (void)size21;
+ std::size_t size22 = buffer_copy(mb1, cb2, 128);
+ (void)size22;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size23 = buffer_copy(mb1, cbc2, 128);
+ (void)size23;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size24 = buffer_copy(mb1, mb2, 128);
+ (void)size24;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size25 = buffer_copy(mb1, mbc2, 128);
+ (void)size25;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size26 = buffer_copy(mb1, const_buffer_sequence, 128);
+ (void)size26;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size27 = buffer_copy(mbc1, cb2, 128);
+ (void)size27;
+ std::size_t size28 = buffer_copy(mbc1, cbc2, 128);
+ (void)size28;
+ std::size_t size29 = buffer_copy(mbc1, mb2, 128);
+ (void)size29;
+ std::size_t size30 = buffer_copy(mbc1, mbc2, 128);
+ (void)size30;
+ std::size_t size31 = buffer_copy(mbc1, const_buffer_sequence, 128);
+ (void)size31;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size32 = buffer_copy(mutable_buffer_sequence, cb2, 128);
+ (void)size32;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size33 = buffer_copy(mutable_buffer_sequence, cbc2, 128);
+ (void)size33;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size34 = buffer_copy(mutable_buffer_sequence, mb2, 128);
+ (void)size34;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size35 = buffer_copy(mutable_buffer_sequence, mbc2, 128);
+ (void)size35;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ std::size_t size36 = buffer_copy(
+ mutable_buffer_sequence, const_buffer_sequence, 128);
+ (void)size36;
+
+ // dynamic_buffer function overloads.
+
+ dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> db1 = dynamic_buffer(string_data);
+ (void)db1;
+ dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> db2 = dynamic_buffer(string_data, 1024);
+ (void)db2;
+ dynamic_vector_buffer<char, std::allocator<char> >
+ db3 = dynamic_buffer(vector_data);
+ (void)db3;
+ dynamic_vector_buffer<char, std::allocator<char> >
+ db4 = dynamic_buffer(vector_data, 1024);
+ (void)db4;
+
+ // dynamic_buffer member functions.
+
+ std::size_t size37 = db1.size();
+ (void)size37;
+ std::size_t size38 = db3.size();
+ (void)size38;
+
+ std::size_t size39 = db1.max_size();
+ (void)size39;
+ std::size_t size40 = db3.max_size();
+ (void)size40;
+
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+ dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type>::const_buffers_type
+ cb5 = db1.data();
+ (void)cb5;
+ dynamic_vector_buffer<char, std::allocator<char> >::const_buffers_type
+ cb6 = db3.data();
+ (void)cb6;
+
+ dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type>::mutable_buffers_type mb5
+ = db1.prepare(1024);
+ (void)mb5;
+ dynamic_vector_buffer<char, std::allocator<char> >::mutable_buffers_type
+ mb6 = db3.prepare(1024);
+ (void)mb6;
+
+ db1.commit(1024);
+ db3.commit(1024);
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+ dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type>::mutable_buffers_type
+ mb7 = db1.data(0, 1);
+ (void)mb7;
+ dynamic_vector_buffer<char, std::allocator<char> >::mutable_buffers_type
+ mb8 = db3.data(0, 1);
+ (void)mb8;
+
+ dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type>::const_buffers_type
+ cb7 = static_cast<const dynamic_string_buffer<char,
+ std::string::traits_type,
+ std::string::allocator_type>&>(db1).data(0, 1);
+ (void)cb7;
+ dynamic_vector_buffer<char, std::allocator<char> >::const_buffers_type
+ cb8 = static_cast<const dynamic_vector_buffer<char,
+ std::allocator<char> >&>(db3).data(0, 1);
+ (void)cb8;
+
+ db1.grow(1024);
+ db3.grow(1024);
+
+ db1.shrink(1024);
+ db3.shrink(1024);
+
+ db1.consume(0);
+ db3.consume(0);
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace buffer_compile
+
+//------------------------------------------------------------------------------
+
+namespace buffer_copy_runtime {
+
+using namespace boost::asio;
+using namespace std;
+
+void test()
+{
+ char dest_data[256];
+ char source_data[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mutable_buffer mb1 = boost::asio::buffer(dest_data);
+ mutable_buffer mb2 = boost::asio::buffer(source_data);
+ std::size_t n = buffer_copy(mb1, mb2);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ const_buffer cb1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mb1, cb1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ mutable_buffers_1 mbc1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mb1, mbc1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ const_buffers_1 cbc1 = const_buffers_1(boost::asio::buffer(source_data));
+ n = buffer_copy(mb1, cbc1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mbc1 = boost::asio::buffer(dest_data);
+ mb1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mbc1, mb1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mbc1 = boost::asio::buffer(dest_data);
+ cb1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mbc1, cb1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mbc1 = boost::asio::buffer(dest_data);
+ mutable_buffers_1 mbc2 = boost::asio::buffer(source_data);
+ n = buffer_copy(mbc1, mbc2);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mbc1 = boost::asio::buffer(dest_data);
+ cbc1 = const_buffers_1(boost::asio::buffer(source_data));
+ n = buffer_copy(mbc1, cbc1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ std::vector<mutable_buffer> mv1;
+ mv1.push_back(boost::asio::buffer(source_data, 5));
+ mv1.push_back(boost::asio::buffer(source_data) + 5);
+ n = buffer_copy(mb1, mv1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ std::vector<const_buffer> cv1;
+ cv1.push_back(boost::asio::buffer(source_data, 6));
+ cv1.push_back(boost::asio::buffer(source_data) + 6);
+ n = buffer_copy(mb1, cv1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mv1.clear();
+ mv1.push_back(boost::asio::buffer(dest_data, 7));
+ mv1.push_back(boost::asio::buffer(dest_data) + 7);
+ cb1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mv1, cb1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mv1.clear();
+ mv1.push_back(boost::asio::buffer(dest_data, 7));
+ mv1.push_back(boost::asio::buffer(dest_data) + 7);
+ cv1.clear();
+ cv1.push_back(boost::asio::buffer(source_data, 8));
+ cv1.push_back(boost::asio::buffer(source_data) + 8);
+ n = buffer_copy(mv1, cv1);
+ BOOST_ASIO_CHECK(n == sizeof(source_data));
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ mb2 = boost::asio::buffer(source_data);
+ n = buffer_copy(mb1, mb2, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ cb1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mb1, cb1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ mbc1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mb1, mbc1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ cbc1 = const_buffers_1(boost::asio::buffer(source_data));
+ n = buffer_copy(mb1, cbc1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mbc1 = boost::asio::buffer(dest_data);
+ mb1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mbc1, mb1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mbc1 = boost::asio::buffer(dest_data);
+ cb1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mbc1, cb1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mbc1 = boost::asio::buffer(dest_data);
+ mbc2 = boost::asio::buffer(source_data);
+ n = buffer_copy(mbc1, mbc2, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mbc1 = boost::asio::buffer(dest_data);
+ cbc1 = const_buffers_1(boost::asio::buffer(source_data));
+ n = buffer_copy(mbc1, cbc1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ mv1.clear();
+ mv1.push_back(boost::asio::buffer(source_data, 5));
+ mv1.push_back(boost::asio::buffer(source_data) + 5);
+ n = buffer_copy(mb1, mv1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mb1 = boost::asio::buffer(dest_data);
+ cv1.clear();
+ cv1.push_back(boost::asio::buffer(source_data, 6));
+ cv1.push_back(boost::asio::buffer(source_data) + 6);
+ n = buffer_copy(mb1, cv1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mv1.clear();
+ mv1.push_back(boost::asio::buffer(dest_data, 7));
+ mv1.push_back(boost::asio::buffer(dest_data) + 7);
+ cb1 = boost::asio::buffer(source_data);
+ n = buffer_copy(mv1, cb1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+
+ memset(dest_data, 0, sizeof(dest_data));
+ mv1.clear();
+ mv1.push_back(boost::asio::buffer(dest_data, 7));
+ mv1.push_back(boost::asio::buffer(dest_data) + 7);
+ cv1.clear();
+ cv1.push_back(boost::asio::buffer(source_data, 8));
+ cv1.push_back(boost::asio::buffer(source_data) + 8);
+ n = buffer_copy(mv1, cv1, 10);
+ BOOST_ASIO_CHECK(n == 10);
+ BOOST_ASIO_CHECK(memcmp(dest_data, source_data, n) == 0);
+}
+
+} // namespace buffer_copy_runtime
+
+//------------------------------------------------------------------------------
+
+namespace buffer_sequence {
+
+using namespace boost::asio;
+using namespace std;
+
+struct valid_const_a
+{
+ typedef const_buffer* const_iterator;
+ typedef const_buffer value_type;
+ const_buffer* begin() const { return 0; }
+ const_buffer* end() const { return 0; }
+};
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE)
+struct valid_const_b
+{
+ const_buffer* begin() const { return 0; }
+ const_buffer* end() const { return 0; }
+};
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
+
+struct valid_mutable_a
+{
+ typedef mutable_buffer* const_iterator;
+ typedef mutable_buffer value_type;
+ mutable_buffer* begin() const { return 0; }
+ mutable_buffer* end() const { return 0; }
+};
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE)
+struct valid_mutable_b
+{
+ mutable_buffer* begin() const { return 0; }
+ mutable_buffer* end() const { return 0; }
+};
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
+
+struct invalid_const_a
+{
+ typedef int value_type;
+ int* begin() const { return 0; }
+ const_buffer* end() const { return 0; }
+};
+
+struct invalid_const_b
+{
+ typedef const_buffer value_type;
+ const_buffer* begin() const { return 0; }
+};
+
+struct invalid_const_c
+{
+ typedef const_buffer value_type;
+ const_buffer* end() const { return 0; }
+};
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE)
+struct invalid_const_d
+{
+ int* begin() const { return 0; }
+ const_buffer* end() const { return 0; }
+};
+
+struct invalid_const_e
+{
+ const_buffer* begin() const { return 0; }
+};
+
+struct invalid_const_f
+{
+ const_buffer* end() const { return 0; }
+};
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
+
+struct invalid_mutable_a
+{
+ typedef int value_type;
+ int* begin() const { return 0; }
+ mutable_buffer* end() const { return 0; }
+};
+
+struct invalid_mutable_b
+{
+ typedef mutable_buffer value_type;
+ mutable_buffer* begin() const { return 0; }
+};
+
+struct invalid_mutable_c
+{
+ typedef mutable_buffer value_type;
+ mutable_buffer* end() const { return 0; }
+};
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE)
+struct invalid_mutable_d
+{
+ int* begin() const { return 0; }
+ mutable_buffer* end() const { return 0; }
+};
+
+struct invalid_mutable_e
+{
+ mutable_buffer* begin() const { return 0; }
+};
+
+struct invalid_mutable_f
+{
+ mutable_buffer* end() const { return 0; }
+};
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
+
+void test()
+{
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<const_buffer>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<const_buffer>::value);
+
+ const_buffer b1;
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b1) == &b1);
+ BOOST_ASIO_CHECK(buffer_sequence_end(b1) == &b1 + 1);
+
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<mutable_buffer>::value);
+ BOOST_ASIO_CHECK(is_mutable_buffer_sequence<mutable_buffer>::value);
+
+ mutable_buffer b2;
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b2) == &b2);
+ BOOST_ASIO_CHECK(buffer_sequence_end(b2) == &b2 + 1);
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<const_buffers_1>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<const_buffers_1>::value);
+
+ const_buffers_1 b3(0, 0);
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b3) == &b3);
+ BOOST_ASIO_CHECK(buffer_sequence_end(b3) == &b3 + 1);
+
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<mutable_buffers_1>::value);
+ BOOST_ASIO_CHECK(is_mutable_buffer_sequence<mutable_buffers_1>::value);
+
+ mutable_buffers_1 b4(0, 0);
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b4) == &b4);
+ BOOST_ASIO_CHECK(buffer_sequence_end(b4) == &b4 + 1);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<vector<const_buffer> >::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<vector<const_buffer> >::value);
+
+ vector<const_buffer> b5;
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b5) == b5.begin());
+ BOOST_ASIO_CHECK(buffer_sequence_end(b5) == b5.end());
+
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<vector<mutable_buffer> >::value);
+ BOOST_ASIO_CHECK(is_mutable_buffer_sequence<vector<mutable_buffer> >::value);
+
+ vector<mutable_buffer> b6;
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b6) == b6.begin());
+ BOOST_ASIO_CHECK(buffer_sequence_end(b6) == b6.end());
+
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<valid_const_a>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<valid_const_a>::value);
+
+ valid_const_a b7;
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b7) == b7.begin());
+ BOOST_ASIO_CHECK(buffer_sequence_end(b7) == b7.end());
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE)
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<valid_const_b>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<valid_const_b>::value);
+
+ valid_const_b b8;
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b8) == b8.begin());
+ BOOST_ASIO_CHECK(buffer_sequence_end(b8) == b8.end());
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
+
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<valid_mutable_a>::value);
+ BOOST_ASIO_CHECK(is_mutable_buffer_sequence<valid_mutable_a>::value);
+
+ valid_mutable_a b9;
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b9) == b9.begin());
+ BOOST_ASIO_CHECK(buffer_sequence_end(b9) == b9.end());
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE)
+ BOOST_ASIO_CHECK(is_const_buffer_sequence<valid_mutable_b>::value);
+ BOOST_ASIO_CHECK(is_mutable_buffer_sequence<valid_mutable_b>::value);
+
+ valid_mutable_b b10;
+ BOOST_ASIO_CHECK(buffer_sequence_begin(b10) == b10.begin());
+ BOOST_ASIO_CHECK(buffer_sequence_end(b10) == b10.end());
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
+
+ BOOST_ASIO_CHECK(!is_const_buffer_sequence<invalid_const_a>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_const_a>::value);
+
+ BOOST_ASIO_CHECK(!is_const_buffer_sequence<invalid_const_b>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_const_b>::value);
+
+ BOOST_ASIO_CHECK(!is_const_buffer_sequence<invalid_const_c>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_const_c>::value);
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE)
+ BOOST_ASIO_CHECK(!is_const_buffer_sequence<invalid_const_d>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_const_d>::value);
+
+ BOOST_ASIO_CHECK(!is_const_buffer_sequence<invalid_const_e>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_const_e>::value);
+
+ BOOST_ASIO_CHECK(!is_const_buffer_sequence<invalid_const_f>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_const_f>::value);
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
+
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_a>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_a>::value);
+
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_b>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_b>::value);
+
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_c>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_c>::value);
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE)
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_d>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_d>::value);
+
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_e>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_e>::value);
+
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_f>::value);
+ BOOST_ASIO_CHECK(!is_mutable_buffer_sequence<invalid_mutable_f>::value);
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
+}
+
+} // namespace buffer_sequence
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "buffer",
+ BOOST_ASIO_COMPILE_TEST_CASE(buffer_compile::test)
+ BOOST_ASIO_TEST_CASE(buffer_copy_runtime::test)
+ BOOST_ASIO_TEST_CASE(buffer_sequence::test)
+)
diff --git a/src/boost/libs/asio/test/buffered_read_stream.cpp b/src/boost/libs/asio/test/buffered_read_stream.cpp
new file mode 100644
index 000000000..0228e8caf
--- /dev/null
+++ b/src/boost/libs/asio/test/buffered_read_stream.cpp
@@ -0,0 +1,338 @@
+//
+// buffered_read_stream.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/buffered_read_stream.hpp>
+
+#include <cstring>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/system/system_error.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <boost/array.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+typedef boost::asio::buffered_read_stream<
+ boost::asio::ip::tcp::socket> stream_type;
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void fill_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test_compile()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ using boost::array;
+#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ using std::array;
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+ using namespace boost::asio;
+
+ try
+ {
+ io_context ioc;
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ array<boost::asio::mutable_buffer, 2> mutable_buffers = {{
+ boost::asio::buffer(mutable_char_buffer, 10),
+ boost::asio::buffer(mutable_char_buffer + 10, 10) }};
+ array<boost::asio::const_buffer, 2> const_buffers = {{
+ boost::asio::buffer(const_char_buffer, 10),
+ boost::asio::buffer(const_char_buffer + 10, 10) }};
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ stream_type stream1(ioc);
+ stream_type stream2(ioc, 1024);
+
+ stream_type::executor_type ex = stream1.get_executor();
+ (void)ex;
+
+ stream_type::lowest_layer_type& lowest_layer = stream1.lowest_layer();
+ (void)lowest_layer;
+
+ stream1.write_some(buffer(mutable_char_buffer));
+ stream1.write_some(buffer(const_char_buffer));
+ stream1.write_some(mutable_buffers);
+ stream1.write_some(const_buffers);
+ stream1.write_some(null_buffers());
+ stream1.write_some(buffer(mutable_char_buffer), ec);
+ stream1.write_some(buffer(const_char_buffer), ec);
+ stream1.write_some(mutable_buffers, ec);
+ stream1.write_some(const_buffers, ec);
+ stream1.write_some(null_buffers(), ec);
+
+ stream1.async_write_some(buffer(mutable_char_buffer), &write_some_handler);
+ stream1.async_write_some(buffer(const_char_buffer), &write_some_handler);
+ stream1.async_write_some(mutable_buffers, &write_some_handler);
+ stream1.async_write_some(const_buffers, &write_some_handler);
+ stream1.async_write_some(null_buffers(), &write_some_handler);
+ int i1 = stream1.async_write_some(buffer(mutable_char_buffer), lazy);
+ (void)i1;
+ int i2 = stream1.async_write_some(buffer(const_char_buffer), lazy);
+ (void)i2;
+ int i3 = stream1.async_write_some(mutable_buffers, lazy);
+ (void)i3;
+ int i4 = stream1.async_write_some(const_buffers, lazy);
+ (void)i4;
+ int i5 = stream1.async_write_some(null_buffers(), lazy);
+ (void)i5;
+
+ stream1.fill();
+ stream1.fill(ec);
+
+ stream1.async_fill(&fill_handler);
+ int i6 = stream1.async_fill(lazy);
+ (void)i6;
+
+ stream1.read_some(buffer(mutable_char_buffer));
+ stream1.read_some(mutable_buffers);
+ stream1.read_some(null_buffers());
+ stream1.read_some(buffer(mutable_char_buffer), ec);
+ stream1.read_some(mutable_buffers, ec);
+ stream1.read_some(null_buffers(), ec);
+
+ stream1.async_read_some(buffer(mutable_char_buffer), &read_some_handler);
+ stream1.async_read_some(mutable_buffers, &read_some_handler);
+ stream1.async_read_some(null_buffers(), &read_some_handler);
+ int i7 = stream1.async_read_some(buffer(mutable_char_buffer), lazy);
+ (void)i7;
+ int i8 = stream1.async_read_some(mutable_buffers, lazy);
+ (void)i8;
+ int i9 = stream1.async_read_some(null_buffers(), lazy);
+ (void)i9;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+void test_sync_operations()
+{
+ using namespace std; // For memcmp.
+
+ boost::asio::io_context io_context;
+
+ boost::asio::ip::tcp::acceptor acceptor(io_context,
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 0));
+ boost::asio::ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+ server_endpoint.address(boost::asio::ip::address_v4::loopback());
+
+ stream_type client_socket(io_context);
+ client_socket.lowest_layer().connect(server_endpoint);
+
+ stream_type server_socket(io_context);
+ acceptor.accept(server_socket.lowest_layer());
+
+ const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ const boost::asio::const_buffer write_buf = boost::asio::buffer(write_data);
+
+ std::size_t bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ bytes_written += client_socket.write_some(
+ boost::asio::buffer(write_buf + bytes_written));
+ }
+
+ char read_data[sizeof(write_data)];
+ const boost::asio::mutable_buffer read_buf = boost::asio::buffer(read_data);
+
+ std::size_t bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ bytes_read += server_socket.read_some(
+ boost::asio::buffer(read_buf + bytes_read));
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ bytes_written += server_socket.write_some(
+ boost::asio::buffer(write_buf + bytes_written));
+ }
+
+ bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ bytes_read += client_socket.read_some(
+ boost::asio::buffer(read_buf + bytes_read));
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ server_socket.close();
+ boost::system::error_code error;
+ bytes_read = client_socket.read_some(
+ boost::asio::buffer(read_buf), error);
+
+ BOOST_ASIO_CHECK(bytes_read == 0);
+ BOOST_ASIO_CHECK(error == boost::asio::error::eof);
+
+ client_socket.close(error);
+}
+
+void handle_accept(const boost::system::error_code& e)
+{
+ BOOST_ASIO_CHECK(!e);
+}
+
+void handle_write(const boost::system::error_code& e,
+ std::size_t bytes_transferred,
+ std::size_t* total_bytes_written)
+{
+ BOOST_ASIO_CHECK(!e);
+ if (e)
+ throw boost::system::system_error(e); // Terminate test.
+ *total_bytes_written += bytes_transferred;
+}
+
+void handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred,
+ std::size_t* total_bytes_read)
+{
+ BOOST_ASIO_CHECK(!e);
+ if (e)
+ throw boost::system::system_error(e); // Terminate test.
+ *total_bytes_read += bytes_transferred;
+}
+
+void handle_read_eof(const boost::system::error_code& e,
+ std::size_t bytes_transferred)
+{
+ BOOST_ASIO_CHECK(e == boost::asio::error::eof);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void test_async_operations()
+{
+ using namespace std; // For memcmp.
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context io_context;
+
+ boost::asio::ip::tcp::acceptor acceptor(io_context,
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 0));
+ boost::asio::ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+ server_endpoint.address(boost::asio::ip::address_v4::loopback());
+
+ stream_type client_socket(io_context);
+ client_socket.lowest_layer().connect(server_endpoint);
+
+ stream_type server_socket(io_context);
+ acceptor.async_accept(server_socket.lowest_layer(), &handle_accept);
+ io_context.run();
+ io_context.restart();
+
+ const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ const boost::asio::const_buffer write_buf = boost::asio::buffer(write_data);
+
+ std::size_t bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ client_socket.async_write_some(
+ boost::asio::buffer(write_buf + bytes_written),
+ bindns::bind(handle_write, _1, _2, &bytes_written));
+ io_context.run();
+ io_context.restart();
+ }
+
+ char read_data[sizeof(write_data)];
+ const boost::asio::mutable_buffer read_buf = boost::asio::buffer(read_data);
+
+ std::size_t bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ server_socket.async_read_some(
+ boost::asio::buffer(read_buf + bytes_read),
+ bindns::bind(handle_read, _1, _2, &bytes_read));
+ io_context.run();
+ io_context.restart();
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ server_socket.async_write_some(
+ boost::asio::buffer(write_buf + bytes_written),
+ bindns::bind(handle_write, _1, _2, &bytes_written));
+ io_context.run();
+ io_context.restart();
+ }
+
+ bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ client_socket.async_read_some(
+ boost::asio::buffer(read_buf + bytes_read),
+ bindns::bind(handle_read, _1, _2, &bytes_read));
+ io_context.run();
+ io_context.restart();
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ server_socket.close();
+ client_socket.async_read_some(boost::asio::buffer(read_buf), handle_read_eof);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "buffered_read_stream",
+ BOOST_ASIO_TEST_CASE(test_compile)
+ BOOST_ASIO_TEST_CASE(test_sync_operations)
+ BOOST_ASIO_TEST_CASE(test_async_operations)
+)
diff --git a/src/boost/libs/asio/test/buffered_stream.cpp b/src/boost/libs/asio/test/buffered_stream.cpp
new file mode 100644
index 000000000..155c0bc5b
--- /dev/null
+++ b/src/boost/libs/asio/test/buffered_stream.cpp
@@ -0,0 +1,364 @@
+//
+// buffered_stream.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/buffered_stream.hpp>
+
+#include <cstring>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/system/system_error.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <boost/array.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+typedef boost::asio::buffered_stream<
+ boost::asio::ip::tcp::socket> stream_type;
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void flush_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void fill_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test_compile()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ using boost::array;
+#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ using std::array;
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+ using namespace boost::asio;
+
+ try
+ {
+ io_context ioc;
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ array<boost::asio::mutable_buffer, 2> mutable_buffers = {{
+ boost::asio::buffer(mutable_char_buffer, 10),
+ boost::asio::buffer(mutable_char_buffer + 10, 10) }};
+ array<boost::asio::const_buffer, 2> const_buffers = {{
+ boost::asio::buffer(const_char_buffer, 10),
+ boost::asio::buffer(const_char_buffer + 10, 10) }};
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ stream_type stream1(ioc);
+ stream_type stream2(ioc, 1024, 1024);
+
+ stream_type::executor_type ex = stream1.get_executor();
+ (void)ex;
+
+ stream_type::lowest_layer_type& lowest_layer = stream1.lowest_layer();
+ (void)lowest_layer;
+
+ stream1.write_some(buffer(mutable_char_buffer));
+ stream1.write_some(buffer(const_char_buffer));
+ stream1.write_some(mutable_buffers);
+ stream1.write_some(const_buffers);
+ stream1.write_some(null_buffers());
+ stream1.write_some(buffer(mutable_char_buffer), ec);
+ stream1.write_some(buffer(const_char_buffer), ec);
+ stream1.write_some(mutable_buffers, ec);
+ stream1.write_some(const_buffers, ec);
+ stream1.write_some(null_buffers(), ec);
+
+ stream1.async_write_some(buffer(mutable_char_buffer), &write_some_handler);
+ stream1.async_write_some(buffer(const_char_buffer), &write_some_handler);
+ stream1.async_write_some(mutable_buffers, &write_some_handler);
+ stream1.async_write_some(const_buffers, &write_some_handler);
+ stream1.async_write_some(null_buffers(), &write_some_handler);
+ int i1 = stream1.async_write_some(buffer(mutable_char_buffer), lazy);
+ (void)i1;
+ int i2 = stream1.async_write_some(buffer(const_char_buffer), lazy);
+ (void)i2;
+ int i3 = stream1.async_write_some(mutable_buffers, lazy);
+ (void)i3;
+ int i4 = stream1.async_write_some(const_buffers, lazy);
+ (void)i4;
+ int i5 = stream1.async_write_some(null_buffers(), lazy);
+ (void)i5;
+
+ stream1.flush();
+ stream1.flush(ec);
+
+ stream1.async_flush(&flush_handler);
+ int i6 = stream1.async_flush(lazy);
+ (void)i6;
+
+ stream1.fill();
+ stream1.fill(ec);
+
+ stream1.async_fill(&fill_handler);
+ int i7 = stream1.async_fill(lazy);
+ (void)i7;
+
+ stream1.read_some(buffer(mutable_char_buffer));
+ stream1.read_some(mutable_buffers);
+ stream1.read_some(null_buffers());
+ stream1.read_some(buffer(mutable_char_buffer), ec);
+ stream1.read_some(mutable_buffers, ec);
+ stream1.read_some(null_buffers(), ec);
+
+ stream1.async_read_some(buffer(mutable_char_buffer), &read_some_handler);
+ stream1.async_read_some(mutable_buffers, &read_some_handler);
+ stream1.async_read_some(null_buffers(), &read_some_handler);
+ int i8 = stream1.async_read_some(buffer(mutable_char_buffer), lazy);
+ (void)i8;
+ int i9 = stream1.async_read_some(mutable_buffers, lazy);
+ (void)i9;
+ int i10 = stream1.async_read_some(null_buffers(), lazy);
+ (void)i10;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+void test_sync_operations()
+{
+ using namespace std; // For memcmp.
+
+ boost::asio::io_context io_context;
+
+ boost::asio::ip::tcp::acceptor acceptor(io_context,
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 0));
+ boost::asio::ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+ server_endpoint.address(boost::asio::ip::address_v4::loopback());
+
+ stream_type client_socket(io_context);
+ client_socket.lowest_layer().connect(server_endpoint);
+
+ stream_type server_socket(io_context);
+ acceptor.accept(server_socket.lowest_layer());
+
+ const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ const boost::asio::const_buffer write_buf = boost::asio::buffer(write_data);
+
+ std::size_t bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ bytes_written += client_socket.write_some(
+ boost::asio::buffer(write_buf + bytes_written));
+ client_socket.flush();
+ }
+
+ char read_data[sizeof(write_data)];
+ const boost::asio::mutable_buffer read_buf = boost::asio::buffer(read_data);
+
+ std::size_t bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ bytes_read += server_socket.read_some(
+ boost::asio::buffer(read_buf + bytes_read));
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ bytes_written += server_socket.write_some(
+ boost::asio::buffer(write_buf + bytes_written));
+ server_socket.flush();
+ }
+
+ bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ bytes_read += client_socket.read_some(
+ boost::asio::buffer(read_buf + bytes_read));
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ server_socket.close();
+ boost::system::error_code error;
+ bytes_read = client_socket.read_some(
+ boost::asio::buffer(read_buf), error);
+
+ BOOST_ASIO_CHECK(bytes_read == 0);
+ BOOST_ASIO_CHECK(error == boost::asio::error::eof);
+
+ client_socket.close(error);
+}
+
+void handle_accept(const boost::system::error_code& e)
+{
+ BOOST_ASIO_CHECK(!e);
+}
+
+void handle_write(const boost::system::error_code& e,
+ std::size_t bytes_transferred,
+ std::size_t* total_bytes_written)
+{
+ BOOST_ASIO_CHECK(!e);
+ if (e)
+ throw boost::system::system_error(e); // Terminate test.
+ *total_bytes_written += bytes_transferred;
+}
+
+void handle_flush(const boost::system::error_code& e)
+{
+ BOOST_ASIO_CHECK(!e);
+}
+
+void handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred,
+ std::size_t* total_bytes_read)
+{
+ BOOST_ASIO_CHECK(!e);
+ if (e)
+ throw boost::system::system_error(e); // Terminate test.
+ *total_bytes_read += bytes_transferred;
+}
+
+void handle_read_eof(const boost::system::error_code& e,
+ std::size_t bytes_transferred)
+{
+ BOOST_ASIO_CHECK(e == boost::asio::error::eof);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void test_async_operations()
+{
+ using namespace std; // For memcmp.
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context io_context;
+
+ boost::asio::ip::tcp::acceptor acceptor(io_context,
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 0));
+ boost::asio::ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+ server_endpoint.address(boost::asio::ip::address_v4::loopback());
+
+ stream_type client_socket(io_context);
+ client_socket.lowest_layer().connect(server_endpoint);
+
+ stream_type server_socket(io_context);
+ acceptor.async_accept(server_socket.lowest_layer(), &handle_accept);
+ io_context.run();
+ io_context.restart();
+
+ const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ const boost::asio::const_buffer write_buf = boost::asio::buffer(write_data);
+
+ std::size_t bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ client_socket.async_write_some(
+ boost::asio::buffer(write_buf + bytes_written),
+ bindns::bind(handle_write, _1, _2, &bytes_written));
+ io_context.run();
+ io_context.restart();
+ client_socket.async_flush(
+ bindns::bind(handle_flush, _1));
+ io_context.run();
+ io_context.restart();
+ }
+
+ char read_data[sizeof(write_data)];
+ const boost::asio::mutable_buffer read_buf = boost::asio::buffer(read_data);
+
+ std::size_t bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ server_socket.async_read_some(
+ boost::asio::buffer(read_buf + bytes_read),
+ bindns::bind(handle_read, _1, _2, &bytes_read));
+ io_context.run();
+ io_context.restart();
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ server_socket.async_write_some(
+ boost::asio::buffer(write_buf + bytes_written),
+ bindns::bind(handle_write, _1, _2, &bytes_written));
+ io_context.run();
+ io_context.restart();
+ server_socket.async_flush(
+ bindns::bind(handle_flush, _1));
+ io_context.run();
+ io_context.restart();
+ }
+
+ bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ client_socket.async_read_some(
+ boost::asio::buffer(read_buf + bytes_read),
+ bindns::bind(handle_read, _1, _2, &bytes_read));
+ io_context.run();
+ io_context.restart();
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ server_socket.close();
+ client_socket.async_read_some(boost::asio::buffer(read_buf), handle_read_eof);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "buffered_stream",
+ BOOST_ASIO_TEST_CASE(test_compile)
+ BOOST_ASIO_TEST_CASE(test_sync_operations)
+ BOOST_ASIO_TEST_CASE(test_async_operations)
+)
diff --git a/src/boost/libs/asio/test/buffered_write_stream.cpp b/src/boost/libs/asio/test/buffered_write_stream.cpp
new file mode 100644
index 000000000..98e50e43a
--- /dev/null
+++ b/src/boost/libs/asio/test/buffered_write_stream.cpp
@@ -0,0 +1,353 @@
+//
+// buffered_write_stream.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/buffered_write_stream.hpp>
+
+#include <cstring>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/system/system_error.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <boost/array.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+typedef boost::asio::buffered_write_stream<
+ boost::asio::ip::tcp::socket> stream_type;
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void flush_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test_compile()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ using boost::array;
+#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ using std::array;
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+ using namespace boost::asio;
+
+ try
+ {
+ io_context ioc;
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ array<boost::asio::mutable_buffer, 2> mutable_buffers = {{
+ boost::asio::buffer(mutable_char_buffer, 10),
+ boost::asio::buffer(mutable_char_buffer + 10, 10) }};
+ array<boost::asio::const_buffer, 2> const_buffers = {{
+ boost::asio::buffer(const_char_buffer, 10),
+ boost::asio::buffer(const_char_buffer + 10, 10) }};
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ stream_type stream1(ioc);
+ stream_type stream2(ioc, 1024);
+
+ stream_type::executor_type ex = stream1.get_executor();
+ (void)ex;
+
+ stream_type::lowest_layer_type& lowest_layer = stream1.lowest_layer();
+ (void)lowest_layer;
+
+ stream1.write_some(buffer(mutable_char_buffer));
+ stream1.write_some(buffer(const_char_buffer));
+ stream1.write_some(mutable_buffers);
+ stream1.write_some(const_buffers);
+ stream1.write_some(null_buffers());
+ stream1.write_some(buffer(mutable_char_buffer), ec);
+ stream1.write_some(buffer(const_char_buffer), ec);
+ stream1.write_some(mutable_buffers, ec);
+ stream1.write_some(const_buffers, ec);
+ stream1.write_some(null_buffers(), ec);
+
+ stream1.async_write_some(buffer(mutable_char_buffer), &write_some_handler);
+ stream1.async_write_some(buffer(const_char_buffer), &write_some_handler);
+ stream1.async_write_some(mutable_buffers, &write_some_handler);
+ stream1.async_write_some(const_buffers, &write_some_handler);
+ stream1.async_write_some(null_buffers(), &write_some_handler);
+ int i1 = stream1.async_write_some(buffer(mutable_char_buffer), lazy);
+ (void)i1;
+ int i2 = stream1.async_write_some(buffer(const_char_buffer), lazy);
+ (void)i2;
+ int i3 = stream1.async_write_some(mutable_buffers, lazy);
+ (void)i3;
+ int i4 = stream1.async_write_some(const_buffers, lazy);
+ (void)i4;
+ int i5 = stream1.async_write_some(null_buffers(), lazy);
+ (void)i5;
+
+ stream1.flush();
+ stream1.flush(ec);
+
+ stream1.async_flush(&flush_handler);
+ int i6 = stream1.async_flush(lazy);
+ (void)i6;
+
+ stream1.read_some(buffer(mutable_char_buffer));
+ stream1.read_some(mutable_buffers);
+ stream1.read_some(null_buffers());
+ stream1.read_some(buffer(mutable_char_buffer), ec);
+ stream1.read_some(mutable_buffers, ec);
+ stream1.read_some(null_buffers(), ec);
+
+ stream1.async_read_some(buffer(mutable_char_buffer), &read_some_handler);
+ stream1.async_read_some(mutable_buffers, &read_some_handler);
+ stream1.async_read_some(null_buffers(), &read_some_handler);
+ int i7 = stream1.async_read_some(buffer(mutable_char_buffer), lazy);
+ (void)i7;
+ int i8 = stream1.async_read_some(mutable_buffers, lazy);
+ (void)i8;
+ int i9 = stream1.async_read_some(null_buffers(), lazy);
+ (void)i9;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+void test_sync_operations()
+{
+ using namespace std; // For memcmp.
+
+ boost::asio::io_context io_context;
+
+ boost::asio::ip::tcp::acceptor acceptor(io_context,
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 0));
+ boost::asio::ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+ server_endpoint.address(boost::asio::ip::address_v4::loopback());
+
+ stream_type client_socket(io_context);
+ client_socket.lowest_layer().connect(server_endpoint);
+
+ stream_type server_socket(io_context);
+ acceptor.accept(server_socket.lowest_layer());
+
+ const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ const boost::asio::const_buffer write_buf = boost::asio::buffer(write_data);
+
+ std::size_t bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ bytes_written += client_socket.write_some(
+ boost::asio::buffer(write_buf + bytes_written));
+ client_socket.flush();
+ }
+
+ char read_data[sizeof(write_data)];
+ const boost::asio::mutable_buffer read_buf = boost::asio::buffer(read_data);
+
+ std::size_t bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ bytes_read += server_socket.read_some(
+ boost::asio::buffer(read_buf + bytes_read));
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ bytes_written += server_socket.write_some(
+ boost::asio::buffer(write_buf + bytes_written));
+ server_socket.flush();
+ }
+
+ bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ bytes_read += client_socket.read_some(
+ boost::asio::buffer(read_buf + bytes_read));
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ server_socket.close();
+ boost::system::error_code error;
+ bytes_read = client_socket.read_some(
+ boost::asio::buffer(read_buf), error);
+
+ BOOST_ASIO_CHECK(bytes_read == 0);
+ BOOST_ASIO_CHECK(error == boost::asio::error::eof);
+
+ client_socket.close(error);
+}
+
+void handle_accept(const boost::system::error_code& e)
+{
+ BOOST_ASIO_CHECK(!e);
+}
+
+void handle_write(const boost::system::error_code& e,
+ std::size_t bytes_transferred,
+ std::size_t* total_bytes_written)
+{
+ BOOST_ASIO_CHECK(!e);
+ if (e)
+ throw boost::system::system_error(e); // Terminate test.
+ *total_bytes_written += bytes_transferred;
+}
+
+void handle_flush(const boost::system::error_code& e)
+{
+ BOOST_ASIO_CHECK(!e);
+}
+
+void handle_read(const boost::system::error_code& e,
+ std::size_t bytes_transferred,
+ std::size_t* total_bytes_read)
+{
+ BOOST_ASIO_CHECK(!e);
+ if (e)
+ throw boost::system::system_error(e); // Terminate test.
+ *total_bytes_read += bytes_transferred;
+}
+
+void handle_read_eof(const boost::system::error_code& e,
+ std::size_t bytes_transferred)
+{
+ BOOST_ASIO_CHECK(e == boost::asio::error::eof);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void test_async_operations()
+{
+ using namespace std; // For memcmp.
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context io_context;
+
+ boost::asio::ip::tcp::acceptor acceptor(io_context,
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 0));
+ boost::asio::ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+ server_endpoint.address(boost::asio::ip::address_v4::loopback());
+
+ stream_type client_socket(io_context);
+ client_socket.lowest_layer().connect(server_endpoint);
+
+ stream_type server_socket(io_context);
+ acceptor.async_accept(server_socket.lowest_layer(), &handle_accept);
+ io_context.run();
+ io_context.restart();
+
+ const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ const boost::asio::const_buffer write_buf = boost::asio::buffer(write_data);
+
+ std::size_t bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ client_socket.async_write_some(
+ boost::asio::buffer(write_buf + bytes_written),
+ bindns::bind(handle_write, _1, _2, &bytes_written));
+ io_context.run();
+ io_context.restart();
+ client_socket.async_flush(
+ bindns::bind(handle_flush, _1));
+ io_context.run();
+ io_context.restart();
+ }
+
+ char read_data[sizeof(write_data)];
+ const boost::asio::mutable_buffer read_buf = boost::asio::buffer(read_data);
+
+ std::size_t bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ server_socket.async_read_some(
+ boost::asio::buffer(read_buf + bytes_read),
+ bindns::bind(handle_read, _1, _2, &bytes_read));
+ io_context.run();
+ io_context.restart();
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ bytes_written = 0;
+ while (bytes_written < sizeof(write_data))
+ {
+ server_socket.async_write_some(
+ boost::asio::buffer(write_buf + bytes_written),
+ bindns::bind(handle_write, _1, _2, &bytes_written));
+ io_context.run();
+ io_context.restart();
+ server_socket.async_flush(
+ bindns::bind(handle_flush, _1));
+ io_context.run();
+ io_context.restart();
+ }
+
+ bytes_read = 0;
+ while (bytes_read < sizeof(read_data))
+ {
+ client_socket.async_read_some(
+ boost::asio::buffer(read_buf + bytes_read),
+ bindns::bind(handle_read, _1, _2, &bytes_read));
+ io_context.run();
+ io_context.restart();
+ }
+
+ BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
+ BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
+ BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);
+
+ server_socket.close();
+ client_socket.async_read_some(boost::asio::buffer(read_buf), handle_read_eof);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "buffered_write_stream",
+ BOOST_ASIO_TEST_CASE(test_compile)
+ BOOST_ASIO_TEST_CASE(test_sync_operations)
+ BOOST_ASIO_TEST_CASE(test_async_operations)
+)
diff --git a/src/boost/libs/asio/test/buffers_iterator.cpp b/src/boost/libs/asio/test/buffers_iterator.cpp
new file mode 100644
index 000000000..caedeae71
--- /dev/null
+++ b/src/boost/libs/asio/test/buffers_iterator.cpp
@@ -0,0 +1,292 @@
+//
+// buffers_iterator.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/buffers_iterator.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <boost/array.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+//------------------------------------------------------------------------------
+
+// buffers_iterator_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all operations on the buffers_iterator compile
+// and link correctly. Runtime failures are ignored.
+
+namespace buffers_iterator_compile {
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+using boost::array;
+#elif defined(BOOST_ASIO_HAS_STD_ARRAY)
+using std::array;
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+using std::vector;
+using namespace boost::asio;
+
+void test()
+{
+ try
+ {
+ char data1[16], data2[16];
+ const char cdata1[16] = "", cdata2[16] = "";
+ mutable_buffer mb1 = buffer(data1);
+ array<mutable_buffer, 2> mb2 = {{ buffer(data1), buffer(data2) }};
+ std::vector<mutable_buffer> mb3;
+ mb3.push_back(buffer(data1));
+ const_buffer cb1 = buffer(cdata1);
+ array<const_buffer, 2> cb2 = {{ buffer(cdata1), buffer(cdata2) }};
+ vector<const_buffer> cb3;
+ cb3.push_back(buffer(cdata1));
+
+
+ // buffers_iterator constructors.
+
+ buffers_iterator<mutable_buffer, char> bi1;
+ buffers_iterator<mutable_buffer, const char> bi2;
+ buffers_iterator<array<mutable_buffer, 2>, char> bi3;
+ buffers_iterator<array<mutable_buffer, 2>, const char> bi4;
+ buffers_iterator<vector<mutable_buffer>, char> bi5;
+ buffers_iterator<vector<mutable_buffer>, const char> bi6;
+ buffers_iterator<const_buffer, char> bi7;
+ buffers_iterator<const_buffer, const char> bi8;
+ buffers_iterator<array<const_buffer, 2>, char> bi9;
+ buffers_iterator<array<const_buffer, 2>, const char> bi10;
+ buffers_iterator<vector<const_buffer>, char> bi11;
+ buffers_iterator<vector<const_buffer>, const char> bi12;
+
+ buffers_iterator<mutable_buffer, char> bi13(
+ buffers_iterator<mutable_buffer, char>::begin(mb1));
+ buffers_iterator<mutable_buffer, const char> bi14(
+ buffers_iterator<mutable_buffer, const char>::begin(mb1));
+ buffers_iterator<array<mutable_buffer, 2>, char> bi15(
+ buffers_iterator<array<mutable_buffer, 2>, char>::begin(mb2));
+ buffers_iterator<array<mutable_buffer, 2>, const char> bi16(
+ buffers_iterator<array<mutable_buffer, 2>, const char>::begin(mb2));
+ buffers_iterator<vector<mutable_buffer>, char> bi17(
+ buffers_iterator<vector<mutable_buffer>, char>::begin(mb3));
+ buffers_iterator<vector<mutable_buffer>, const char> bi18(
+ buffers_iterator<vector<mutable_buffer>, const char>::begin(mb3));
+ buffers_iterator<const_buffer, char> bi19(
+ buffers_iterator<const_buffer, char>::begin(cb1));
+ buffers_iterator<const_buffer, const char> bi20(
+ buffers_iterator<const_buffer, const char>::begin(cb1));
+ buffers_iterator<array<const_buffer, 2>, char> bi21(
+ buffers_iterator<array<const_buffer, 2>, char>::begin(cb2));
+ buffers_iterator<array<const_buffer, 2>, const char> bi22(
+ buffers_iterator<array<const_buffer, 2>, const char>::begin(cb2));
+ buffers_iterator<vector<const_buffer>, char> bi23(
+ buffers_iterator<vector<const_buffer>, char>::begin(cb3));
+ buffers_iterator<vector<const_buffer>, const char> bi24(
+ buffers_iterator<vector<const_buffer>, const char>::begin(cb3));
+
+ // buffers_iterator member functions.
+
+ bi1 = buffers_iterator<mutable_buffer, char>::begin(mb1);
+ bi2 = buffers_iterator<mutable_buffer, const char>::begin(mb1);
+ bi3 = buffers_iterator<array<mutable_buffer, 2>, char>::begin(mb2);
+ bi4 = buffers_iterator<array<mutable_buffer, 2>, const char>::begin(mb2);
+ bi5 = buffers_iterator<vector<mutable_buffer>, char>::begin(mb3);
+ bi6 = buffers_iterator<vector<mutable_buffer>, const char>::begin(mb3);
+ bi7 = buffers_iterator<const_buffer, char>::begin(cb1);
+ bi8 = buffers_iterator<const_buffer, const char>::begin(cb1);
+ bi9 = buffers_iterator<array<const_buffer, 2>, char>::begin(cb2);
+ bi10 = buffers_iterator<array<const_buffer, 2>, const char>::begin(cb2);
+ bi11 = buffers_iterator<vector<const_buffer>, char>::begin(cb3);
+ bi12 = buffers_iterator<vector<const_buffer>, const char>::begin(cb3);
+
+ bi1 = buffers_iterator<mutable_buffer, char>::end(mb1);
+ bi2 = buffers_iterator<mutable_buffer, const char>::end(mb1);
+ bi3 = buffers_iterator<array<mutable_buffer, 2>, char>::end(mb2);
+ bi4 = buffers_iterator<array<mutable_buffer, 2>, const char>::end(mb2);
+ bi5 = buffers_iterator<vector<mutable_buffer>, char>::end(mb3);
+ bi6 = buffers_iterator<vector<mutable_buffer>, const char>::end(mb3);
+ bi7 = buffers_iterator<const_buffer, char>::end(cb1);
+ bi8 = buffers_iterator<const_buffer, const char>::end(cb1);
+ bi9 = buffers_iterator<array<const_buffer, 2>, char>::end(cb2);
+ bi10 = buffers_iterator<array<const_buffer, 2>, const char>::end(cb2);
+ bi11 = buffers_iterator<vector<const_buffer>, char>::end(cb3);
+ bi12 = buffers_iterator<vector<const_buffer>, const char>::end(cb3);
+
+ // buffers_iterator related functions.
+
+ bi1 = buffers_begin(mb1);
+ bi3 = buffers_begin(mb2);
+ bi5 = buffers_begin(mb3);
+ bi7 = buffers_begin(cb1);
+ bi9 = buffers_begin(cb2);
+ bi11 = buffers_begin(cb3);
+
+ bi1 = buffers_end(mb1);
+ bi3 = buffers_end(mb2);
+ bi5 = buffers_end(mb3);
+ bi7 = buffers_end(cb1);
+ bi9 = buffers_end(cb2);
+ bi11 = buffers_end(cb3);
+
+ // RandomAccessIterator operations.
+
+ --bi1;
+ --bi2;
+ --bi3;
+ --bi4;
+ --bi5;
+ --bi6;
+ --bi7;
+ --bi8;
+ --bi9;
+ --bi10;
+ --bi11;
+ --bi12;
+
+ ++bi1;
+ ++bi2;
+ ++bi3;
+ ++bi4;
+ ++bi5;
+ ++bi6;
+ ++bi7;
+ ++bi8;
+ ++bi9;
+ ++bi10;
+ ++bi11;
+ ++bi12;
+
+ bi1--;
+ bi2--;
+ bi3--;
+ bi4--;
+ bi5--;
+ bi6--;
+ bi7--;
+ bi8--;
+ bi9--;
+ bi10--;
+ bi11--;
+ bi12--;
+
+ bi1++;
+ bi2++;
+ bi3++;
+ bi4++;
+ bi5++;
+ bi6++;
+ bi7++;
+ bi8++;
+ bi9++;
+ bi10++;
+ bi11++;
+ bi12++;
+
+ bi1 -= 1;
+ bi2 -= 1;
+ bi3 -= 1;
+ bi4 -= 1;
+ bi5 -= 1;
+ bi6 -= 1;
+ bi7 -= 1;
+ bi8 -= 1;
+ bi9 -= 1;
+ bi10 -= 1;
+ bi11 -= 1;
+ bi12 -= 1;
+
+ bi1 += 1;
+ bi2 += 1;
+ bi3 += 1;
+ bi4 += 1;
+ bi5 += 1;
+ bi6 += 1;
+ bi7 += 1;
+ bi8 += 1;
+ bi9 += 1;
+ bi10 += 1;
+ bi11 += 1;
+ bi12 += 1;
+
+ bi1 = bi1 - 1;
+ bi2 = bi2 - 1;
+ bi3 = bi3 - 1;
+ bi4 = bi4 - 1;
+ bi5 = bi5 - 1;
+ bi6 = bi6 - 1;
+ bi7 = bi7 - 1;
+ bi8 = bi8 - 1;
+ bi9 = bi9 - 1;
+ bi10 = bi10 - 1;
+ bi11 = bi11 - 1;
+ bi12 = bi12 - 1;
+
+ bi1 = bi1 + 1;
+ bi2 = bi2 + 1;
+ bi3 = bi3 + 1;
+ bi4 = bi4 + 1;
+ bi5 = bi5 + 1;
+ bi6 = bi6 + 1;
+ bi7 = bi7 + 1;
+ bi8 = bi8 + 1;
+ bi9 = bi9 + 1;
+ bi10 = bi10 + 1;
+ bi11 = bi11 + 1;
+ bi12 = bi12 + 1;
+
+ bi1 = (-1) + bi1;
+ bi2 = (-1) + bi2;
+ bi3 = (-1) + bi3;
+ bi4 = (-1) + bi4;
+ bi5 = (-1) + bi5;
+ bi6 = (-1) + bi6;
+ bi7 = (-1) + bi7;
+ bi8 = (-1) + bi8;
+ bi9 = (-1) + bi9;
+ bi10 = (-1) + bi10;
+ bi11 = (-1) + bi11;
+ bi12 = (-1) + bi12;
+
+ (void)static_cast<std::ptrdiff_t>(bi13 - bi1);
+ (void)static_cast<std::ptrdiff_t>(bi14 - bi2);
+ (void)static_cast<std::ptrdiff_t>(bi15 - bi3);
+ (void)static_cast<std::ptrdiff_t>(bi16 - bi4);
+ (void)static_cast<std::ptrdiff_t>(bi17 - bi5);
+ (void)static_cast<std::ptrdiff_t>(bi18 - bi6);
+ (void)static_cast<std::ptrdiff_t>(bi19 - bi7);
+ (void)static_cast<std::ptrdiff_t>(bi20 - bi8);
+ (void)static_cast<std::ptrdiff_t>(bi21 - bi9);
+ (void)static_cast<std::ptrdiff_t>(bi22 - bi10);
+ (void)static_cast<std::ptrdiff_t>(bi23 - bi11);
+ (void)static_cast<std::ptrdiff_t>(bi24 - bi12);
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace buffers_iterator_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "buffers_iterator",
+ BOOST_ASIO_TEST_CASE(buffers_iterator_compile::test)
+)
diff --git a/src/boost/libs/asio/test/co_spawn.cpp b/src/boost/libs/asio/test/co_spawn.cpp
new file mode 100644
index 000000000..da88ceb55
--- /dev/null
+++ b/src/boost/libs/asio/test/co_spawn.cpp
@@ -0,0 +1,25 @@
+//
+// co_spawn.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/co_spawn.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "co_spawn",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/completion_condition.cpp b/src/boost/libs/asio/test/completion_condition.cpp
new file mode 100644
index 000000000..4f5971bca
--- /dev/null
+++ b/src/boost/libs/asio/test/completion_condition.cpp
@@ -0,0 +1,25 @@
+//
+// completion_condition.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/completion_condition.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "completion_condition",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/compose.cpp b/src/boost/libs/asio/test/compose.cpp
new file mode 100644
index 000000000..3255ef824
--- /dev/null
+++ b/src/boost/libs/asio/test/compose.cpp
@@ -0,0 +1,185 @@
+//
+// compose.cpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/compose.hpp>
+
+#include "unit_test.hpp"
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/post.hpp>
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+//------------------------------------------------------------------------------
+
+class impl_0_completion_args
+{
+public:
+ explicit impl_0_completion_args(boost::asio::io_context& ioc)
+ : ioc_(ioc),
+ state_(starting)
+ {
+ }
+
+ template <typename Self>
+ void operator()(Self& self)
+ {
+ switch (state_)
+ {
+ case starting:
+ state_ = posting;
+ boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self));
+ break;
+ case posting:
+ self.complete();
+ break;
+ default:
+ break;
+ }
+ }
+
+private:
+ boost::asio::io_context& ioc_;
+ enum { starting, posting } state_;
+};
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void())
+async_0_completion_args(boost::asio::io_context& ioc,
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ return boost::asio::async_compose<CompletionToken, void()>(
+ impl_0_completion_args(ioc), token);
+}
+
+void compose_0_args_handler(int* count)
+{
+ ++(*count);
+}
+
+void compose_0_completion_args_test()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+ boost::asio::io_context ioc;
+ int count = 0;
+
+ async_0_completion_args(ioc, bindns::bind(&compose_0_args_handler, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 1);
+}
+
+//------------------------------------------------------------------------------
+
+class impl_1_completion_arg
+{
+public:
+ explicit impl_1_completion_arg(boost::asio::io_context& ioc)
+ : ioc_(ioc),
+ state_(starting)
+ {
+ }
+
+ template <typename Self>
+ void operator()(Self& self)
+ {
+ switch (state_)
+ {
+ case starting:
+ state_ = posting;
+ boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self));
+ break;
+ case posting:
+ self.complete(42);
+ break;
+ default:
+ break;
+ }
+ }
+
+private:
+ boost::asio::io_context& ioc_;
+ enum { starting, posting } state_;
+};
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int))
+async_1_completion_arg(boost::asio::io_context& ioc,
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ return boost::asio::async_compose<CompletionToken, void(int)>(
+ impl_1_completion_arg(ioc), token);
+}
+
+void compose_1_args_handler(int* count, int* result_out, int result)
+{
+ ++(*count);
+ *result_out = result;
+}
+
+void compose_1_completion_arg_test()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+
+ boost::asio::io_context ioc;
+ int count = 0;
+ int result = 0;
+
+ async_1_completion_arg(ioc,
+ bindns::bind(&compose_1_args_handler, &count, &result, _1));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+ BOOST_ASIO_CHECK(result == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 1);
+ BOOST_ASIO_CHECK(result == 42);
+}
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "compose",
+ BOOST_ASIO_TEST_CASE(compose_0_completion_args_test)
+ BOOST_ASIO_TEST_CASE(compose_1_completion_arg_test)
+)
diff --git a/src/boost/libs/asio/test/connect.cpp b/src/boost/libs/asio/test/connect.cpp
new file mode 100644
index 000000000..32f9cbd15
--- /dev/null
+++ b/src/boost/libs/asio/test/connect.cpp
@@ -0,0 +1,1190 @@
+//
+// connect.cpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/connect.hpp>
+
+#include <vector>
+#include <boost/asio/detail/thread.hpp>
+#include <boost/asio/ip/tcp.hpp>
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+using bindns::placeholders::_1;
+using bindns::placeholders::_2;
+
+class connection_sink
+{
+public:
+ connection_sink()
+ : acceptor_(io_context_,
+ boost::asio::ip::tcp::endpoint(
+ boost::asio::ip::address_v4::loopback(), 0)),
+ target_endpoint_(acceptor_.local_endpoint()),
+ socket_(io_context_),
+ thread_(bindns::bind(&connection_sink::run, this))
+ {
+ }
+
+ ~connection_sink()
+ {
+ io_context_.stop();
+ thread_.join();
+ }
+
+ boost::asio::ip::tcp::endpoint target_endpoint()
+ {
+ return target_endpoint_;
+ }
+
+private:
+ void run()
+ {
+ io_context_.run();
+ }
+
+ void handle_accept()
+ {
+ socket_.close();
+ acceptor_.async_accept(socket_,
+ bindns::bind(&connection_sink::handle_accept, this));
+ }
+
+ boost::asio::io_context io_context_;
+ boost::asio::ip::tcp::acceptor acceptor_;
+ boost::asio::ip::tcp::endpoint target_endpoint_;
+ boost::asio::ip::tcp::socket socket_;
+ boost::asio::detail::thread thread_;
+};
+
+bool true_cond_1(const boost::system::error_code& /*ec*/,
+ const boost::asio::ip::tcp::endpoint& /*endpoint*/)
+{
+ return true;
+}
+
+struct true_cond_2
+{
+ template <typename Endpoint>
+ bool operator()(const boost::system::error_code& /*ec*/,
+ const Endpoint& /*endpoint*/)
+ {
+ return true;
+ }
+};
+
+std::vector<boost::asio::ip::tcp::endpoint>::const_iterator legacy_true_cond_1(
+ const boost::system::error_code& /*ec*/,
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator next)
+{
+ return next;
+}
+
+struct legacy_true_cond_2
+{
+ template <typename Iterator>
+ Iterator operator()(const boost::system::error_code& /*ec*/, Iterator next)
+ {
+ return next;
+ }
+};
+
+bool false_cond(const boost::system::error_code& /*ec*/,
+ const boost::asio::ip::tcp::endpoint& /*endpoint*/)
+{
+ return false;
+}
+
+void range_handler(const boost::system::error_code& ec,
+ const boost::asio::ip::tcp::endpoint& endpoint,
+ boost::system::error_code* out_ec,
+ boost::asio::ip::tcp::endpoint* out_endpoint)
+{
+ *out_ec = ec;
+ *out_endpoint = endpoint;
+}
+
+void iter_handler(const boost::system::error_code& ec,
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator iter,
+ boost::system::error_code* out_ec,
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator* out_iter)
+{
+ *out_ec = ec;
+ *out_iter = iter;
+}
+
+void test_connect_range()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ boost::asio::ip::tcp::endpoint result;
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, endpoints);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, endpoints);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ result = boost::asio::connect(socket, endpoints);
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+}
+
+void test_connect_range_ec()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ boost::asio::ip::tcp::endpoint result;
+ boost::system::error_code ec;
+
+ result = boost::asio::connect(socket, endpoints, ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, endpoints, ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, endpoints, ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ result = boost::asio::connect(socket, endpoints, ec);
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+}
+
+void test_connect_range_cond()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ boost::asio::ip::tcp::endpoint result;
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints, true_cond_1);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints, true_cond_2());
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_1);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_2());
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints, false_cond);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, endpoints, true_cond_1);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ result = boost::asio::connect(socket, endpoints, true_cond_2());
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_1);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_2());
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints, false_cond);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, endpoints, true_cond_1);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ result = boost::asio::connect(socket, endpoints, true_cond_2());
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_1);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_2());
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints, false_cond);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ result = boost::asio::connect(socket, endpoints, true_cond_1);
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+
+ result = boost::asio::connect(socket, endpoints, true_cond_2());
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_1);
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_2());
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+
+ try
+ {
+ result = boost::asio::connect(socket, endpoints, false_cond);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+}
+
+void test_connect_range_cond_ec()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ boost::asio::ip::tcp::endpoint result;
+ boost::system::error_code ec;
+
+ result = boost::asio::connect(socket, endpoints, true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ result = boost::asio::connect(socket, endpoints, true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ result = boost::asio::connect(socket, endpoints, false_cond, ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, endpoints, true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, false_cond, ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, endpoints, true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, false_cond, ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ result = boost::asio::connect(socket, endpoints, true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, legacy_true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, endpoints, false_cond, ec);
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+}
+
+void test_connect_iter()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ const std::vector<boost::asio::ip::tcp::endpoint>& cendpoints = endpoints;
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator result;
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(), cendpoints.end());
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(), cendpoints.end());
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(), cendpoints.end());
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(), cendpoints.end());
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+}
+
+void test_connect_iter_ec()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ const std::vector<boost::asio::ip::tcp::endpoint>& cendpoints = endpoints;
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator result;
+ boost::system::error_code ec;
+
+ result = boost::asio::connect(socket,
+ cendpoints.begin(), cendpoints.end(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket,
+ cendpoints.begin(), cendpoints.end(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket,
+ cendpoints.begin(), cendpoints.end(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ result = boost::asio::connect(socket,
+ cendpoints.begin(), cendpoints.end(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+}
+
+void test_connect_iter_cond()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ const std::vector<boost::asio::ip::tcp::endpoint>& cendpoints = endpoints;
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator result;
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_1);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_2());
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_1);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_2());
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), false_cond);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_1);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_2());
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_1);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_2());
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), false_cond);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_1);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_2());
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_1);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_2());
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), false_cond);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_1);
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_2());
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_1);
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_2());
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+
+ try
+ {
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), false_cond);
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::not_found);
+ }
+}
+
+void test_connect_iter_cond_ec()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ const std::vector<boost::asio::ip::tcp::endpoint>& cendpoints = endpoints;
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator result;
+ boost::system::error_code ec;
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), false_cond, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), false_cond, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), false_cond, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_1, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), legacy_true_cond_2(), ec);
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+
+ result = boost::asio::connect(socket, cendpoints.begin(),
+ cendpoints.end(), false_cond, ec);
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+}
+
+void test_async_connect_range()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ boost::asio::ip::tcp::endpoint result;
+ boost::system::error_code ec;
+
+ boost::asio::async_connect(socket, endpoints,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ boost::asio::async_connect(socket, endpoints,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ boost::asio::async_connect(socket, endpoints,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ boost::asio::async_connect(socket, endpoints,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+}
+
+void test_async_connect_range_cond()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ boost::asio::ip::tcp::endpoint result;
+ boost::system::error_code ec;
+
+ boost::asio::async_connect(socket, endpoints, true_cond_1,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ boost::asio::async_connect(socket, endpoints, true_cond_2(),
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ boost::asio::async_connect(socket, endpoints, legacy_true_cond_1,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ boost::asio::async_connect(socket, endpoints, legacy_true_cond_2(),
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ boost::asio::async_connect(socket, endpoints, false_cond,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ boost::asio::async_connect(socket, endpoints, true_cond_1,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, true_cond_2(),
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, legacy_true_cond_1,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, legacy_true_cond_2(),
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, false_cond,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ boost::asio::async_connect(socket, endpoints, true_cond_1,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, true_cond_2(),
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, legacy_true_cond_1,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, legacy_true_cond_2(),
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[0]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, false_cond,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ boost::asio::async_connect(socket, endpoints, true_cond_1,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, true_cond_2(),
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, legacy_true_cond_1,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, legacy_true_cond_2(),
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == endpoints[1]);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, endpoints, false_cond,
+ bindns::bind(range_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == boost::asio::ip::tcp::endpoint());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+}
+
+void test_async_connect_iter()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ const std::vector<boost::asio::ip::tcp::endpoint>& cendpoints = endpoints;
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator result;
+ boost::system::error_code ec;
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+}
+
+void test_async_connect_iter_cond()
+{
+ connection_sink sink;
+ boost::asio::io_context io_context;
+ boost::asio::ip::tcp::socket socket(io_context);
+ std::vector<boost::asio::ip::tcp::endpoint> endpoints;
+ const std::vector<boost::asio::ip::tcp::endpoint>& cendpoints = endpoints;
+ std::vector<boost::asio::ip::tcp::endpoint>::const_iterator result;
+ boost::system::error_code ec;
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ true_cond_1, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ true_cond_2(), bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ legacy_true_cond_1, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ legacy_true_cond_2(), bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ false_cond, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ true_cond_1, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ true_cond_2(), bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ legacy_true_cond_1, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ legacy_true_cond_2(), bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ false_cond, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.push_back(sink.target_endpoint());
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ true_cond_1, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ true_cond_2(), bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ legacy_true_cond_1, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ legacy_true_cond_2(), bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin());
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ false_cond, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+
+ endpoints.insert(endpoints.begin(), boost::asio::ip::tcp::endpoint());
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ true_cond_1, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ true_cond_2(), bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ legacy_true_cond_1, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ legacy_true_cond_2(), bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.begin() + 1);
+ BOOST_ASIO_CHECK(!ec);
+
+ boost::asio::async_connect(socket, cendpoints.begin(), cendpoints.end(),
+ false_cond, bindns::bind(iter_handler, _1, _2, &ec, &result));
+ io_context.restart();
+ io_context.run();
+ BOOST_ASIO_CHECK(result == cendpoints.end());
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "connect",
+ BOOST_ASIO_TEST_CASE(test_connect_range)
+ BOOST_ASIO_TEST_CASE(test_connect_range_ec)
+ BOOST_ASIO_TEST_CASE(test_connect_range_cond)
+ BOOST_ASIO_TEST_CASE(test_connect_range_cond_ec)
+ BOOST_ASIO_TEST_CASE(test_connect_iter)
+ BOOST_ASIO_TEST_CASE(test_connect_iter_ec)
+ BOOST_ASIO_TEST_CASE(test_connect_iter_cond)
+ BOOST_ASIO_TEST_CASE(test_connect_iter_cond_ec)
+ BOOST_ASIO_TEST_CASE(test_async_connect_range)
+ BOOST_ASIO_TEST_CASE(test_async_connect_range_cond)
+ BOOST_ASIO_TEST_CASE(test_async_connect_iter)
+ BOOST_ASIO_TEST_CASE(test_async_connect_iter_cond)
+)
diff --git a/src/boost/libs/asio/test/coroutine.cpp b/src/boost/libs/asio/test/coroutine.cpp
new file mode 100644
index 000000000..703feb67d
--- /dev/null
+++ b/src/boost/libs/asio/test/coroutine.cpp
@@ -0,0 +1,112 @@
+//
+// coroutine.cpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/coroutine.hpp>
+
+#include "unit_test.hpp"
+
+// Must come after all other headers.
+#include <boost/asio/yield.hpp>
+
+//------------------------------------------------------------------------------
+
+// Coroutine completes via yield break.
+
+void yield_break_coro(boost::asio::coroutine& coro)
+{
+ reenter (coro)
+ {
+ yield return;
+ yield break;
+ }
+}
+
+void yield_break_test()
+{
+ boost::asio::coroutine coro;
+ BOOST_ASIO_CHECK(!coro.is_complete());
+ yield_break_coro(coro);
+ BOOST_ASIO_CHECK(!coro.is_complete());
+ yield_break_coro(coro);
+ BOOST_ASIO_CHECK(coro.is_complete());
+}
+
+//------------------------------------------------------------------------------
+
+// Coroutine completes via return.
+
+void return_coro(boost::asio::coroutine& coro)
+{
+ reenter (coro)
+ {
+ return;
+ }
+}
+
+void return_test()
+{
+ boost::asio::coroutine coro;
+ return_coro(coro);
+ BOOST_ASIO_CHECK(coro.is_complete());
+}
+
+//------------------------------------------------------------------------------
+
+// Coroutine completes via exception.
+
+void exception_coro(boost::asio::coroutine& coro)
+{
+ reenter (coro)
+ {
+ throw 1;
+ }
+}
+
+void exception_test()
+{
+ boost::asio::coroutine coro;
+ try { exception_coro(coro); } catch (int) {}
+ BOOST_ASIO_CHECK(coro.is_complete());
+}
+
+//------------------------------------------------------------------------------
+
+// Coroutine completes by falling off the end.
+
+void fall_off_end_coro(boost::asio::coroutine& coro)
+{
+ reenter (coro)
+ {
+ }
+}
+
+void fall_off_end_test()
+{
+ boost::asio::coroutine coro;
+ fall_off_end_coro(coro);
+ BOOST_ASIO_CHECK(coro.is_complete());
+}
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "coroutine",
+ BOOST_ASIO_TEST_CASE(yield_break_test)
+ BOOST_ASIO_TEST_CASE(return_test)
+ BOOST_ASIO_TEST_CASE(exception_test)
+ BOOST_ASIO_TEST_CASE(fall_off_end_test)
+)
diff --git a/src/boost/libs/asio/test/deadline_timer.cpp b/src/boost/libs/asio/test/deadline_timer.cpp
new file mode 100644
index 000000000..0ff0d9bd8
--- /dev/null
+++ b/src/boost/libs/asio/test/deadline_timer.cpp
@@ -0,0 +1,392 @@
+//
+// deadline_timer.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/deadline_timer.hpp>
+
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+#include <boost/bind/bind.hpp>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/placeholders.hpp>
+#include <boost/asio/detail/thread.hpp>
+
+using namespace boost::posix_time;
+
+void increment(int* count)
+{
+ ++(*count);
+}
+
+void decrement_to_zero(boost::asio::deadline_timer* t, int* count)
+{
+ if (*count > 0)
+ {
+ --(*count);
+
+ int before_value = *count;
+
+ t->expires_at(t->expires_at() + seconds(1));
+ t->async_wait(boost::bind(decrement_to_zero, t, count));
+
+ // Completion cannot nest, so count value should remain unchanged.
+ BOOST_ASIO_CHECK(*count == before_value);
+ }
+}
+
+void increment_if_not_cancelled(int* count,
+ const boost::system::error_code& ec)
+{
+ if (!ec)
+ ++(*count);
+}
+
+void cancel_timer(boost::asio::deadline_timer* t)
+{
+ std::size_t num_cancelled = t->cancel();
+ BOOST_ASIO_CHECK(num_cancelled == 1);
+}
+
+void cancel_one_timer(boost::asio::deadline_timer* t)
+{
+ std::size_t num_cancelled = t->cancel_one();
+ BOOST_ASIO_CHECK(num_cancelled == 1);
+}
+
+ptime now()
+{
+#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
+ return microsec_clock::universal_time();
+#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
+ return second_clock::universal_time();
+#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
+}
+
+void deadline_timer_test()
+{
+ boost::asio::io_context ioc;
+ int count = 0;
+
+ ptime start = now();
+
+ boost::asio::deadline_timer t1(ioc, seconds(1));
+ t1.wait();
+
+ // The timer must block until after its expiry time.
+ ptime end = now();
+ ptime expected_end = start + seconds(1);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ start = now();
+
+ boost::asio::deadline_timer t2(ioc, seconds(1) + microseconds(500000));
+ t2.wait();
+
+ // The timer must block until after its expiry time.
+ end = now();
+ expected_end = start + seconds(1) + microseconds(500000);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ t2.expires_at(t2.expires_at() + seconds(1));
+ t2.wait();
+
+ // The timer must block until after its expiry time.
+ end = now();
+ expected_end += seconds(1);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ start = now();
+
+ t2.expires_from_now(seconds(1) + microseconds(200000));
+ t2.wait();
+
+ // The timer must block until after its expiry time.
+ end = now();
+ expected_end = start + seconds(1) + microseconds(200000);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ start = now();
+
+ boost::asio::deadline_timer t3(ioc, seconds(5));
+ t3.async_wait(boost::bind(increment, &count));
+
+ // No completions can be delivered until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all operations have finished, and
+ // this should not be until after the timer's expiry time.
+ BOOST_ASIO_CHECK(count == 1);
+ end = now();
+ expected_end = start + seconds(1);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ count = 3;
+ start = now();
+
+ boost::asio::deadline_timer t4(ioc, seconds(1));
+ t4.async_wait(boost::bind(decrement_to_zero, &t4, &count));
+
+ // No completions can be delivered until run() is called.
+ BOOST_ASIO_CHECK(count == 3);
+
+ ioc.restart();
+ ioc.run();
+
+ // The run() call will not return until all operations have finished, and
+ // this should not be until after the timer's final expiry time.
+ BOOST_ASIO_CHECK(count == 0);
+ end = now();
+ expected_end = start + seconds(3);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ count = 0;
+ start = now();
+
+ boost::asio::deadline_timer t5(ioc, seconds(10));
+ t5.async_wait(boost::bind(increment_if_not_cancelled, &count,
+ boost::asio::placeholders::error));
+ boost::asio::deadline_timer t6(ioc, seconds(1));
+ t6.async_wait(boost::bind(cancel_timer, &t5));
+
+ // No completions can be delivered until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ ioc.run();
+
+ // The timer should have been cancelled, so count should not have changed.
+ // The total run time should not have been much more than 1 second (and
+ // certainly far less than 10 seconds).
+ BOOST_ASIO_CHECK(count == 0);
+ end = now();
+ expected_end = start + seconds(2);
+ BOOST_ASIO_CHECK(end < expected_end);
+
+ // Wait on the timer again without cancelling it. This time the asynchronous
+ // wait should run to completion and increment the counter.
+ t5.async_wait(boost::bind(increment_if_not_cancelled, &count,
+ boost::asio::placeholders::error));
+
+ ioc.restart();
+ ioc.run();
+
+ // The timer should not have been cancelled, so count should have changed.
+ // The total time since the timer was created should be more than 10 seconds.
+ BOOST_ASIO_CHECK(count == 1);
+ end = now();
+ expected_end = start + seconds(10);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ count = 0;
+ start = now();
+
+ // Start two waits on a timer, one of which will be cancelled. The one
+ // which is not cancelled should still run to completion and increment the
+ // counter.
+ boost::asio::deadline_timer t7(ioc, seconds(3));
+ t7.async_wait(boost::bind(increment_if_not_cancelled, &count,
+ boost::asio::placeholders::error));
+ t7.async_wait(boost::bind(increment_if_not_cancelled, &count,
+ boost::asio::placeholders::error));
+ boost::asio::deadline_timer t8(ioc, seconds(1));
+ t8.async_wait(boost::bind(cancel_one_timer, &t7));
+
+ ioc.restart();
+ ioc.run();
+
+ // One of the waits should not have been cancelled, so count should have
+ // changed. The total time since the timer was created should be more than 3
+ // seconds.
+ BOOST_ASIO_CHECK(count == 1);
+ end = now();
+ expected_end = start + seconds(3);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+}
+
+void timer_handler(const boost::system::error_code&)
+{
+}
+
+void deadline_timer_cancel_test()
+{
+ static boost::asio::io_context io_context;
+ struct timer
+ {
+ boost::asio::deadline_timer t;
+ timer() : t(io_context) { t.expires_at(boost::posix_time::pos_infin); }
+ } timers[50];
+
+ timers[2].t.async_wait(&timer_handler);
+ timers[41].t.async_wait(&timer_handler);
+ for (int i = 10; i < 20; ++i)
+ timers[i].t.async_wait(&timer_handler);
+
+ BOOST_ASIO_CHECK(timers[2].t.cancel() == 1);
+ BOOST_ASIO_CHECK(timers[41].t.cancel() == 1);
+ for (int i = 10; i < 20; ++i)
+ BOOST_ASIO_CHECK(timers[i].t.cancel() == 1);
+}
+
+struct custom_allocation_timer_handler
+{
+ custom_allocation_timer_handler(int* count) : count_(count) {}
+ void operator()(const boost::system::error_code&) {}
+ int* count_;
+};
+
+void* asio_handler_allocate(std::size_t size,
+ custom_allocation_timer_handler* handler)
+{
+ ++(*handler->count_);
+ return ::operator new(size);
+}
+
+void asio_handler_deallocate(void* pointer, std::size_t,
+ custom_allocation_timer_handler* handler)
+{
+ --(*handler->count_);
+ ::operator delete(pointer);
+}
+
+void deadline_timer_custom_allocation_test()
+{
+ static boost::asio::io_context io_context;
+ struct timer
+ {
+ boost::asio::deadline_timer t;
+ timer() : t(io_context) {}
+ } timers[100];
+
+ int allocation_count = 0;
+
+ for (int i = 0; i < 50; ++i)
+ {
+ timers[i].t.expires_at(boost::posix_time::pos_infin);
+ timers[i].t.async_wait(custom_allocation_timer_handler(&allocation_count));
+ }
+
+ for (int i = 50; i < 100; ++i)
+ {
+ timers[i].t.expires_at(boost::posix_time::neg_infin);
+ timers[i].t.async_wait(custom_allocation_timer_handler(&allocation_count));
+ }
+
+ for (int i = 0; i < 50; ++i)
+ timers[i].t.cancel();
+
+ io_context.run();
+
+ BOOST_ASIO_CHECK(allocation_count == 0);
+}
+
+void io_context_run(boost::asio::io_context* ioc)
+{
+ ioc->run();
+}
+
+void deadline_timer_thread_test()
+{
+ boost::asio::io_context ioc;
+ boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work
+ = boost::asio::make_work_guard(ioc);
+ boost::asio::deadline_timer t1(ioc);
+ boost::asio::deadline_timer t2(ioc);
+ int count = 0;
+
+ boost::asio::detail::thread th(boost::bind(io_context_run, &ioc));
+
+ t2.expires_from_now(boost::posix_time::seconds(2));
+ t2.wait();
+
+ t1.expires_from_now(boost::posix_time::seconds(2));
+ t1.async_wait(boost::bind(increment, &count));
+
+ t2.expires_from_now(boost::posix_time::seconds(4));
+ t2.wait();
+
+ ioc.stop();
+ th.join();
+
+ BOOST_ASIO_CHECK(count == 1);
+}
+
+void deadline_timer_async_result_test()
+{
+ boost::asio::io_context ioc;
+ boost::asio::deadline_timer t1(ioc);
+
+ t1.expires_from_now(boost::posix_time::seconds(1));
+ int i = t1.async_wait(archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+
+ ioc.run();
+}
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+boost::asio::deadline_timer make_timer(boost::asio::io_context& ioc, int* count)
+{
+ boost::asio::deadline_timer t(ioc);
+ t.expires_from_now(boost::posix_time::seconds(1));
+ t.async_wait(boost::bind(increment, count));
+ return t;
+}
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+void deadline_timer_move_test()
+{
+#if defined(BOOST_ASIO_HAS_MOVE)
+ boost::asio::io_context io_context1;
+ boost::asio::io_context io_context2;
+ int count = 0;
+
+ boost::asio::deadline_timer t1 = make_timer(io_context1, &count);
+ boost::asio::deadline_timer t2 = make_timer(io_context2, &count);
+ boost::asio::deadline_timer t3 = std::move(t1);
+
+ t2 = std::move(t1);
+
+ io_context2.run();
+
+ BOOST_ASIO_CHECK(count == 1);
+
+ io_context1.run();
+
+ BOOST_ASIO_CHECK(count == 2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "deadline_timer",
+ BOOST_ASIO_TEST_CASE(deadline_timer_test)
+ BOOST_ASIO_TEST_CASE(deadline_timer_cancel_test)
+ BOOST_ASIO_TEST_CASE(deadline_timer_custom_allocation_test)
+ BOOST_ASIO_TEST_CASE(deadline_timer_thread_test)
+ BOOST_ASIO_TEST_CASE(deadline_timer_async_result_test)
+ BOOST_ASIO_TEST_CASE(deadline_timer_move_test)
+)
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+BOOST_ASIO_TEST_SUITE
+(
+ "deadline_timer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
diff --git a/src/boost/libs/asio/test/defer.cpp b/src/boost/libs/asio/test/defer.cpp
new file mode 100644
index 000000000..49e85fe24
--- /dev/null
+++ b/src/boost/libs/asio/test/defer.cpp
@@ -0,0 +1,25 @@
+//
+// defer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/defer.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "defer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/detached.cpp b/src/boost/libs/asio/test/detached.cpp
new file mode 100644
index 000000000..2c62e6d66
--- /dev/null
+++ b/src/boost/libs/asio/test/detached.cpp
@@ -0,0 +1,25 @@
+//
+// detached.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/detached.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "detached",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/dispatch.cpp b/src/boost/libs/asio/test/dispatch.cpp
new file mode 100644
index 000000000..f97531469
--- /dev/null
+++ b/src/boost/libs/asio/test/dispatch.cpp
@@ -0,0 +1,25 @@
+//
+// dispatch.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/dispatch.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "dispatch",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/error.cpp b/src/boost/libs/asio/test/error.cpp
new file mode 100644
index 000000000..5be958401
--- /dev/null
+++ b/src/boost/libs/asio/test/error.cpp
@@ -0,0 +1,89 @@
+//
+// error.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/error.hpp>
+
+#include <sstream>
+#include "unit_test.hpp"
+
+void test_error_code(const boost::system::error_code& code)
+{
+ boost::system::error_code error(code);
+ BOOST_ASIO_CHECK(code == error);
+
+ BOOST_ASIO_CHECK(!code || error);
+ BOOST_ASIO_CHECK(!code || !!error);
+
+ boost::system::error_code error2(error);
+ BOOST_ASIO_CHECK(error == error2);
+ BOOST_ASIO_CHECK(!(error != error2));
+
+ boost::system::error_code error3;
+ error3 = error;
+ BOOST_ASIO_CHECK(error == error3);
+ BOOST_ASIO_CHECK(!(error != error3));
+
+ std::ostringstream os;
+ os << error;
+ BOOST_ASIO_CHECK(!os.str().empty());
+}
+
+void error_test()
+{
+ test_error_code(boost::asio::error::access_denied);
+ test_error_code(boost::asio::error::address_family_not_supported);
+ test_error_code(boost::asio::error::address_in_use);
+ test_error_code(boost::asio::error::already_connected);
+ test_error_code(boost::asio::error::already_started);
+ test_error_code(boost::asio::error::connection_aborted);
+ test_error_code(boost::asio::error::connection_refused);
+ test_error_code(boost::asio::error::connection_reset);
+ test_error_code(boost::asio::error::bad_descriptor);
+ test_error_code(boost::asio::error::eof);
+ test_error_code(boost::asio::error::fault);
+ test_error_code(boost::asio::error::host_not_found);
+ test_error_code(boost::asio::error::host_not_found_try_again);
+ test_error_code(boost::asio::error::host_unreachable);
+ test_error_code(boost::asio::error::in_progress);
+ test_error_code(boost::asio::error::interrupted);
+ test_error_code(boost::asio::error::invalid_argument);
+ test_error_code(boost::asio::error::message_size);
+ test_error_code(boost::asio::error::network_down);
+ test_error_code(boost::asio::error::network_reset);
+ test_error_code(boost::asio::error::network_unreachable);
+ test_error_code(boost::asio::error::no_descriptors);
+ test_error_code(boost::asio::error::no_buffer_space);
+ test_error_code(boost::asio::error::no_data);
+ test_error_code(boost::asio::error::no_memory);
+ test_error_code(boost::asio::error::no_permission);
+ test_error_code(boost::asio::error::no_protocol_option);
+ test_error_code(boost::asio::error::no_recovery);
+ test_error_code(boost::asio::error::not_connected);
+ test_error_code(boost::asio::error::not_socket);
+ test_error_code(boost::asio::error::operation_aborted);
+ test_error_code(boost::asio::error::operation_not_supported);
+ test_error_code(boost::asio::error::service_not_found);
+ test_error_code(boost::asio::error::shut_down);
+ test_error_code(boost::asio::error::timed_out);
+ test_error_code(boost::asio::error::try_again);
+ test_error_code(boost::asio::error::would_block);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "error",
+ BOOST_ASIO_TEST_CASE(error_test)
+)
diff --git a/src/boost/libs/asio/test/execution_context.cpp b/src/boost/libs/asio/test/execution_context.cpp
new file mode 100644
index 000000000..feea39c87
--- /dev/null
+++ b/src/boost/libs/asio/test/execution_context.cpp
@@ -0,0 +1,25 @@
+//
+// execution_context.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/execution_context.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "execution_context",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/executor.cpp b/src/boost/libs/asio/test/executor.cpp
new file mode 100644
index 000000000..4b6bd7aa4
--- /dev/null
+++ b/src/boost/libs/asio/test/executor.cpp
@@ -0,0 +1,25 @@
+//
+// executor.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/executor.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "executor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/executor_work_guard.cpp b/src/boost/libs/asio/test/executor_work_guard.cpp
new file mode 100644
index 000000000..b27df7bd4
--- /dev/null
+++ b/src/boost/libs/asio/test/executor_work_guard.cpp
@@ -0,0 +1,25 @@
+//
+// executor_work_guard.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/executor_work_guard.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "executor_work_guard",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/generic/basic_endpoint.cpp b/src/boost/libs/asio/test/generic/basic_endpoint.cpp
new file mode 100644
index 000000000..c9522a7d0
--- /dev/null
+++ b/src/boost/libs/asio/test/generic/basic_endpoint.cpp
@@ -0,0 +1,25 @@
+//
+// generic/basic_endpoint.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/generic/basic_endpoint.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "generic/basic_endpoint",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/generic/datagram_protocol.cpp b/src/boost/libs/asio/test/generic/datagram_protocol.cpp
new file mode 100644
index 000000000..76184edf2
--- /dev/null
+++ b/src/boost/libs/asio/test/generic/datagram_protocol.cpp
@@ -0,0 +1,263 @@
+//
+// generic/datagram_protocol.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/generic/datagram_protocol.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include "../unit_test.hpp"
+
+#if defined(__cplusplus_cli) || defined(__cplusplus_winrt)
+# define generic cpp_generic
+#endif
+
+//------------------------------------------------------------------------------
+
+// generic_datagram_protocol_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// generic::datagram_socket::socket compile and link correctly. Runtime
+// failures are ignored.
+
+namespace generic_datagram_protocol_socket_compile {
+
+void connect_handler(const boost::system::error_code&)
+{
+}
+
+void send_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void receive_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+ using namespace boost::asio;
+ namespace generic = boost::asio::generic;
+ typedef generic::datagram_protocol dp;
+
+ const int af_inet = BOOST_ASIO_OS_DEF(AF_INET);
+ const int ipproto_udp = BOOST_ASIO_OS_DEF(IPPROTO_UDP);
+ const int sock_dgram = BOOST_ASIO_OS_DEF(SOCK_DGRAM);
+
+ try
+ {
+ io_context ioc;
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ socket_base::message_flags in_flags = 0;
+ socket_base::send_buffer_size socket_option;
+ socket_base::bytes_readable io_control_command;
+ boost::system::error_code ec;
+
+ // basic_datagram_socket constructors.
+
+ dp::socket socket1(ioc);
+ dp::socket socket2(ioc, dp(af_inet, ipproto_udp));
+ dp::socket socket3(ioc, dp::endpoint());
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ dp::socket::native_handle_type native_socket1
+ = ::socket(af_inet, sock_dgram, 0);
+ dp::socket socket4(ioc, dp(af_inet, ipproto_udp), native_socket1);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ dp::socket socket5(std::move(socket4));
+ boost::asio::ip::udp::socket udp_socket(ioc);
+ dp::socket socket6(std::move(udp_socket));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_datagram_socket operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ socket1 = dp::socket(ioc);
+ socket1 = std::move(socket2);
+ socket1 = boost::asio::ip::udp::socket(ioc);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ dp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ dp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ socket1.open(dp(af_inet, ipproto_udp));
+ socket1.open(dp(af_inet, ipproto_udp), ec);
+
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ dp::socket::native_handle_type native_socket2
+ = ::socket(af_inet, sock_dgram, 0);
+ socket1.assign(dp(af_inet, ipproto_udp), native_socket2);
+ dp::socket::native_handle_type native_socket3
+ = ::socket(af_inet, sock_dgram, 0);
+ socket1.assign(dp(af_inet, ipproto_udp), native_socket3, ec);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ dp::socket::native_handle_type native_socket4 = socket1.native_handle();
+ (void)native_socket4;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(dp::endpoint());
+ socket1.bind(dp::endpoint(), ec);
+
+ socket1.connect(dp::endpoint());
+ socket1.connect(dp::endpoint(), ec);
+
+ socket1.async_connect(dp::endpoint(), connect_handler);
+
+ socket1.set_option(socket_option);
+ socket1.set_option(socket_option, ec);
+
+ socket1.get_option(socket_option);
+ socket1.get_option(socket_option, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ dp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ dp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ dp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ dp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ // basic_datagram_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer));
+ socket1.send(buffer(const_char_buffer));
+ socket1.send(null_buffers());
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), send_handler);
+ socket1.async_send(buffer(const_char_buffer), send_handler);
+ socket1.async_send(null_buffers(), send_handler);
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler);
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler);
+ socket1.async_send(null_buffers(), in_flags, send_handler);
+
+ socket1.send_to(buffer(mutable_char_buffer),
+ dp::endpoint());
+ socket1.send_to(buffer(const_char_buffer),
+ dp::endpoint());
+ socket1.send_to(null_buffers(),
+ dp::endpoint());
+ socket1.send_to(buffer(mutable_char_buffer),
+ dp::endpoint(), in_flags);
+ socket1.send_to(buffer(const_char_buffer),
+ dp::endpoint(), in_flags);
+ socket1.send_to(null_buffers(),
+ dp::endpoint(), in_flags);
+ socket1.send_to(buffer(mutable_char_buffer),
+ dp::endpoint(), in_flags, ec);
+ socket1.send_to(buffer(const_char_buffer),
+ dp::endpoint(), in_flags, ec);
+ socket1.send_to(null_buffers(),
+ dp::endpoint(), in_flags, ec);
+
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ dp::endpoint(), send_handler);
+ socket1.async_send_to(buffer(const_char_buffer),
+ dp::endpoint(), send_handler);
+ socket1.async_send_to(null_buffers(),
+ dp::endpoint(), send_handler);
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ dp::endpoint(), in_flags, send_handler);
+ socket1.async_send_to(buffer(const_char_buffer),
+ dp::endpoint(), in_flags, send_handler);
+ socket1.async_send_to(null_buffers(),
+ dp::endpoint(), in_flags, send_handler);
+
+ socket1.receive(buffer(mutable_char_buffer));
+ socket1.receive(null_buffers());
+ socket1.receive(buffer(mutable_char_buffer), in_flags);
+ socket1.receive(null_buffers(), in_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.receive(null_buffers(), in_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), receive_handler);
+ socket1.async_receive(null_buffers(), receive_handler);
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ receive_handler);
+ socket1.async_receive(null_buffers(), in_flags, receive_handler);
+
+ dp::endpoint endpoint;
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint);
+ socket1.receive_from(null_buffers(), endpoint);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags);
+ socket1.receive_from(null_buffers(), endpoint, in_flags);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags, ec);
+ socket1.receive_from(null_buffers(), endpoint, in_flags, ec);
+
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, receive_handler);
+ socket1.async_receive_from(null_buffers(),
+ endpoint, receive_handler);
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, in_flags, receive_handler);
+ socket1.async_receive_from(null_buffers(),
+ endpoint, in_flags, receive_handler);
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace generic_datagram_protocol_socket_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "generic/datagram_protocol",
+ BOOST_ASIO_TEST_CASE(generic_datagram_protocol_socket_compile::test)
+)
diff --git a/src/boost/libs/asio/test/generic/raw_protocol.cpp b/src/boost/libs/asio/test/generic/raw_protocol.cpp
new file mode 100644
index 000000000..35bb98636
--- /dev/null
+++ b/src/boost/libs/asio/test/generic/raw_protocol.cpp
@@ -0,0 +1,263 @@
+//
+// generic/raw_protocol.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/generic/raw_protocol.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/icmp.hpp>
+#include "../unit_test.hpp"
+
+#if defined(__cplusplus_cli) || defined(__cplusplus_winrt)
+# define generic cpp_generic
+#endif
+
+//------------------------------------------------------------------------------
+
+// generic_raw_protocol_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// generic::raw_socket::socket compile and link correctly. Runtime failures
+// are ignored.
+
+namespace generic_raw_protocol_socket_compile {
+
+void connect_handler(const boost::system::error_code&)
+{
+}
+
+void send_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void receive_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+ using namespace boost::asio;
+ namespace generic = boost::asio::generic;
+ typedef generic::raw_protocol rp;
+
+ const int af_inet = BOOST_ASIO_OS_DEF(AF_INET);
+ const int ipproto_icmp = BOOST_ASIO_OS_DEF(IPPROTO_ICMP);
+ const int sock_raw = BOOST_ASIO_OS_DEF(SOCK_RAW);
+
+ try
+ {
+ io_context ioc;
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ socket_base::message_flags in_flags = 0;
+ socket_base::send_buffer_size socket_option;
+ socket_base::bytes_readable io_control_command;
+ boost::system::error_code ec;
+
+ // basic_raw_socket constructors.
+
+ rp::socket socket1(ioc);
+ rp::socket socket2(ioc, rp(af_inet, ipproto_icmp));
+ rp::socket socket3(ioc, rp::endpoint());
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ rp::socket::native_handle_type native_socket1
+ = ::socket(af_inet, sock_raw, 0);
+ rp::socket socket4(ioc, rp(af_inet, ipproto_icmp), native_socket1);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ rp::socket socket5(std::move(socket4));
+ boost::asio::ip::icmp::socket icmp_socket(ioc);
+ rp::socket socket6(std::move(icmp_socket));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_datagram_socket operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ socket1 = rp::socket(ioc);
+ socket1 = std::move(socket2);
+ socket1 = boost::asio::ip::icmp::socket(ioc);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ rp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ rp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ socket1.open(rp(af_inet, ipproto_icmp));
+ socket1.open(rp(af_inet, ipproto_icmp), ec);
+
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ rp::socket::native_handle_type native_socket2
+ = ::socket(af_inet, sock_raw, 0);
+ socket1.assign(rp(af_inet, ipproto_icmp), native_socket2);
+ rp::socket::native_handle_type native_socket3
+ = ::socket(af_inet, sock_raw, 0);
+ socket1.assign(rp(af_inet, ipproto_icmp), native_socket3, ec);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ rp::socket::native_handle_type native_socket4 = socket1.native_handle();
+ (void)native_socket4;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(rp::endpoint());
+ socket1.bind(rp::endpoint(), ec);
+
+ socket1.connect(rp::endpoint());
+ socket1.connect(rp::endpoint(), ec);
+
+ socket1.async_connect(rp::endpoint(), connect_handler);
+
+ socket1.set_option(socket_option);
+ socket1.set_option(socket_option, ec);
+
+ socket1.get_option(socket_option);
+ socket1.get_option(socket_option, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ rp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ rp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ rp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ rp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ // basic_raw_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer));
+ socket1.send(buffer(const_char_buffer));
+ socket1.send(null_buffers());
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), send_handler);
+ socket1.async_send(buffer(const_char_buffer), send_handler);
+ socket1.async_send(null_buffers(), send_handler);
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler);
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler);
+ socket1.async_send(null_buffers(), in_flags, send_handler);
+
+ socket1.send_to(buffer(mutable_char_buffer),
+ rp::endpoint());
+ socket1.send_to(buffer(const_char_buffer),
+ rp::endpoint());
+ socket1.send_to(null_buffers(),
+ rp::endpoint());
+ socket1.send_to(buffer(mutable_char_buffer),
+ rp::endpoint(), in_flags);
+ socket1.send_to(buffer(const_char_buffer),
+ rp::endpoint(), in_flags);
+ socket1.send_to(null_buffers(),
+ rp::endpoint(), in_flags);
+ socket1.send_to(buffer(mutable_char_buffer),
+ rp::endpoint(), in_flags, ec);
+ socket1.send_to(buffer(const_char_buffer),
+ rp::endpoint(), in_flags, ec);
+ socket1.send_to(null_buffers(),
+ rp::endpoint(), in_flags, ec);
+
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ rp::endpoint(), send_handler);
+ socket1.async_send_to(buffer(const_char_buffer),
+ rp::endpoint(), send_handler);
+ socket1.async_send_to(null_buffers(),
+ rp::endpoint(), send_handler);
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ rp::endpoint(), in_flags, send_handler);
+ socket1.async_send_to(buffer(const_char_buffer),
+ rp::endpoint(), in_flags, send_handler);
+ socket1.async_send_to(null_buffers(),
+ rp::endpoint(), in_flags, send_handler);
+
+ socket1.receive(buffer(mutable_char_buffer));
+ socket1.receive(null_buffers());
+ socket1.receive(buffer(mutable_char_buffer), in_flags);
+ socket1.receive(null_buffers(), in_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.receive(null_buffers(), in_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), receive_handler);
+ socket1.async_receive(null_buffers(), receive_handler);
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ receive_handler);
+ socket1.async_receive(null_buffers(), in_flags, receive_handler);
+
+ rp::endpoint endpoint;
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint);
+ socket1.receive_from(null_buffers(), endpoint);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags);
+ socket1.receive_from(null_buffers(), endpoint, in_flags);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags, ec);
+ socket1.receive_from(null_buffers(), endpoint, in_flags, ec);
+
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, receive_handler);
+ socket1.async_receive_from(null_buffers(),
+ endpoint, receive_handler);
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, in_flags, receive_handler);
+ socket1.async_receive_from(null_buffers(),
+ endpoint, in_flags, receive_handler);
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace generic_raw_protocol_socket_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "generic/raw_protocol",
+ BOOST_ASIO_TEST_CASE(generic_raw_protocol_socket_compile::test)
+)
diff --git a/src/boost/libs/asio/test/generic/seq_packet_protocol.cpp b/src/boost/libs/asio/test/generic/seq_packet_protocol.cpp
new file mode 100644
index 000000000..bf6135654
--- /dev/null
+++ b/src/boost/libs/asio/test/generic/seq_packet_protocol.cpp
@@ -0,0 +1,205 @@
+//
+// generic/seq_packet_protocol.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/generic/seq_packet_protocol.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include "../unit_test.hpp"
+
+#if defined(__cplusplus_cli) || defined(__cplusplus_winrt)
+# define generic cpp_generic
+#endif
+
+//------------------------------------------------------------------------------
+
+// generic_seq_packet_protocol_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// generic::seq_packet_socket::socket compile and link correctly. Runtime
+// failures are ignored.
+
+namespace generic_seq_packet_protocol_socket_compile {
+
+void connect_handler(const boost::system::error_code&)
+{
+}
+
+void send_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void receive_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+ using namespace boost::asio;
+ namespace generic = boost::asio::generic;
+ typedef generic::seq_packet_protocol spp;
+
+ const int af_inet = BOOST_ASIO_OS_DEF(AF_INET);
+ const int sock_seqpacket = BOOST_ASIO_OS_DEF(SOCK_SEQPACKET);
+
+ try
+ {
+ io_context ioc;
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ const socket_base::message_flags in_flags = 0;
+ socket_base::message_flags out_flags = 0;
+ socket_base::send_buffer_size socket_option;
+ socket_base::bytes_readable io_control_command;
+ boost::system::error_code ec;
+
+ // basic_seq_packet_socket constructors.
+
+ spp::socket socket1(ioc);
+ spp::socket socket2(ioc, spp(af_inet, 0));
+ spp::socket socket3(ioc, spp::endpoint());
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ spp::socket::native_handle_type native_socket1
+ = ::socket(af_inet, sock_seqpacket, 0);
+ spp::socket socket4(ioc, spp(af_inet, 0), native_socket1);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ spp::socket socket5(std::move(socket4));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_seq_packet_socket operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ socket1 = spp::socket(ioc);
+ socket1 = std::move(socket2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ spp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ spp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ socket1.open(spp(af_inet, 0));
+ socket1.open(spp(af_inet, 0), ec);
+
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ spp::socket::native_handle_type native_socket2
+ = ::socket(af_inet, sock_seqpacket, 0);
+ socket1.assign(spp(af_inet, 0), native_socket2);
+ spp::socket::native_handle_type native_socket3
+ = ::socket(af_inet, sock_seqpacket, 0);
+ socket1.assign(spp(af_inet, 0), native_socket3, ec);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ spp::socket::native_handle_type native_socket4 = socket1.native_handle();
+ (void)native_socket4;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(spp::endpoint());
+ socket1.bind(spp::endpoint(), ec);
+
+ socket1.connect(spp::endpoint());
+ socket1.connect(spp::endpoint(), ec);
+
+ socket1.async_connect(spp::endpoint(), connect_handler);
+
+ socket1.set_option(socket_option);
+ socket1.set_option(socket_option, ec);
+
+ socket1.get_option(socket_option);
+ socket1.get_option(socket_option, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ spp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ spp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ spp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ spp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ // basic_seq_packet_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler);
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler);
+ socket1.async_send(null_buffers(), in_flags, send_handler);
+
+ socket1.receive(buffer(mutable_char_buffer), out_flags);
+ socket1.receive(null_buffers(), out_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, out_flags);
+ socket1.receive(null_buffers(), in_flags, out_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, out_flags, ec);
+ socket1.receive(null_buffers(), in_flags, out_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), out_flags,
+ receive_handler);
+ socket1.async_receive(null_buffers(), out_flags, receive_handler);
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ out_flags, receive_handler);
+ socket1.async_receive(null_buffers(), in_flags, out_flags, receive_handler);
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace generic_seq_packet_protocol_socket_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "generic/seq_packet_protocol",
+ BOOST_ASIO_TEST_CASE(generic_seq_packet_protocol_socket_compile::test)
+)
diff --git a/src/boost/libs/asio/test/generic/stream_protocol.cpp b/src/boost/libs/asio/test/generic/stream_protocol.cpp
new file mode 100644
index 000000000..23176677b
--- /dev/null
+++ b/src/boost/libs/asio/test/generic/stream_protocol.cpp
@@ -0,0 +1,248 @@
+//
+// generic/stream_protocol.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/generic/stream_protocol.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include "../unit_test.hpp"
+
+#if defined(__cplusplus_cli) || defined(__cplusplus_winrt)
+# define generic cpp_generic
+#endif
+
+//------------------------------------------------------------------------------
+
+// generic_stream_protocol_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// generic::stream_protocol::socket compile and link correctly. Runtime
+// failures are ignored.
+
+namespace generic_stream_protocol_socket_compile {
+
+void connect_handler(const boost::system::error_code&)
+{
+}
+
+void send_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void receive_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+ using namespace boost::asio;
+ namespace generic = boost::asio::generic;
+ typedef generic::stream_protocol sp;
+
+ const int af_inet = BOOST_ASIO_OS_DEF(AF_INET);
+ const int ipproto_tcp = BOOST_ASIO_OS_DEF(IPPROTO_TCP);
+ const int sock_stream = BOOST_ASIO_OS_DEF(SOCK_STREAM);
+
+ try
+ {
+ io_context ioc;
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ socket_base::message_flags in_flags = 0;
+ socket_base::keep_alive socket_option;
+ socket_base::bytes_readable io_control_command;
+ boost::system::error_code ec;
+
+ // basic_stream_socket constructors.
+
+ sp::socket socket1(ioc);
+ sp::socket socket2(ioc, sp(af_inet, ipproto_tcp));
+ sp::socket socket3(ioc, sp::endpoint());
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ Windows::Networking::Sockets::StreamSocket^ native_socket1 = nullptr;
+#else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ sp::socket::native_handle_type native_socket1
+ = ::socket(af_inet, sock_stream, 0);
+#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ sp::socket socket4(ioc, sp(af_inet, ipproto_tcp), native_socket1);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ sp::socket socket5(std::move(socket4));
+ boost::asio::ip::tcp::socket tcp_socket(ioc);
+ sp::socket socket6(std::move(tcp_socket));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_stream_socket operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ socket1 = sp::socket(ioc);
+ socket1 = std::move(socket2);
+ socket1 = boost::asio::ip::tcp::socket(ioc);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ sp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ sp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ socket1.open(sp(af_inet, ipproto_tcp));
+ socket1.open(sp(af_inet, ipproto_tcp), ec);
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ Windows::Networking::Sockets::StreamSocket^ native_socket2 = nullptr;
+#else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ sp::socket::native_handle_type native_socket2
+ = ::socket(af_inet, sock_stream, 0);
+#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ socket1.assign(sp(af_inet, ipproto_tcp), native_socket2);
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ Windows::Networking::Sockets::StreamSocket^ native_socket3 = nullptr;
+#else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ sp::socket::native_handle_type native_socket3
+ = ::socket(af_inet, sock_stream, 0);
+#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ socket1.assign(sp(af_inet, ipproto_tcp), native_socket3, ec);
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ sp::socket::native_handle_type native_socket4 = socket1.native_handle();
+ (void)native_socket4;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(sp::endpoint());
+ socket1.bind(sp::endpoint(), ec);
+
+ socket1.connect(sp::endpoint());
+ socket1.connect(sp::endpoint(), ec);
+
+ socket1.async_connect(sp::endpoint(), connect_handler);
+
+ socket1.set_option(socket_option);
+ socket1.set_option(socket_option, ec);
+
+ socket1.get_option(socket_option);
+ socket1.get_option(socket_option, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ sp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ sp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ sp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ sp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ // basic_stream_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer));
+ socket1.send(buffer(const_char_buffer));
+ socket1.send(null_buffers());
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), send_handler);
+ socket1.async_send(buffer(const_char_buffer), send_handler);
+ socket1.async_send(null_buffers(), send_handler);
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler);
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler);
+ socket1.async_send(null_buffers(), in_flags, send_handler);
+
+ socket1.receive(buffer(mutable_char_buffer));
+ socket1.receive(null_buffers());
+ socket1.receive(buffer(mutable_char_buffer), in_flags);
+ socket1.receive(null_buffers(), in_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.receive(null_buffers(), in_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), receive_handler);
+ socket1.async_receive(null_buffers(), receive_handler);
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ receive_handler);
+ socket1.async_receive(null_buffers(), in_flags, receive_handler);
+
+ socket1.write_some(buffer(mutable_char_buffer));
+ socket1.write_some(buffer(const_char_buffer));
+ socket1.write_some(null_buffers());
+ socket1.write_some(buffer(mutable_char_buffer), ec);
+ socket1.write_some(buffer(const_char_buffer), ec);
+ socket1.write_some(null_buffers(), ec);
+
+ socket1.async_write_some(buffer(mutable_char_buffer), write_some_handler);
+ socket1.async_write_some(buffer(const_char_buffer), write_some_handler);
+ socket1.async_write_some(null_buffers(), write_some_handler);
+
+ socket1.read_some(buffer(mutable_char_buffer));
+ socket1.read_some(buffer(mutable_char_buffer), ec);
+ socket1.read_some(null_buffers(), ec);
+
+ socket1.async_read_some(buffer(mutable_char_buffer), read_some_handler);
+ socket1.async_read_some(null_buffers(), read_some_handler);
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace generic_stream_protocol_socket_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "generic/stream_protocol",
+ BOOST_ASIO_TEST_CASE(generic_stream_protocol_socket_compile::test)
+)
diff --git a/src/boost/libs/asio/test/high_resolution_timer.cpp b/src/boost/libs/asio/test/high_resolution_timer.cpp
new file mode 100644
index 000000000..a667f872c
--- /dev/null
+++ b/src/boost/libs/asio/test/high_resolution_timer.cpp
@@ -0,0 +1,30 @@
+//
+// high_resolution_timer.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/high_resolution_timer.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "high_resolution_timer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/io_context.cpp b/src/boost/libs/asio/test/io_context.cpp
new file mode 100644
index 000000000..7b2ff982f
--- /dev/null
+++ b/src/boost/libs/asio/test/io_context.cpp
@@ -0,0 +1,362 @@
+//
+// io_context.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/io_context.hpp>
+
+#include <sstream>
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/detail/thread.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/deadline_timer.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/steady_timer.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+using namespace boost::asio;
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = std;
+#endif
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+typedef deadline_timer timer;
+namespace chronons = boost::posix_time;
+#elif defined(BOOST_ASIO_HAS_CHRONO)
+typedef steady_timer timer;
+namespace chronons = boost::asio::chrono;
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+void increment(int* count)
+{
+ ++(*count);
+}
+
+void decrement_to_zero(io_context* ioc, int* count)
+{
+ if (*count > 0)
+ {
+ --(*count);
+
+ int before_value = *count;
+ boost::asio::post(*ioc, bindns::bind(decrement_to_zero, ioc, count));
+
+ // Handler execution cannot nest, so count value should remain unchanged.
+ BOOST_ASIO_CHECK(*count == before_value);
+ }
+}
+
+void nested_decrement_to_zero(io_context* ioc, int* count)
+{
+ if (*count > 0)
+ {
+ --(*count);
+
+ boost::asio::dispatch(*ioc,
+ bindns::bind(nested_decrement_to_zero, ioc, count));
+
+ // Handler execution is nested, so count value should now be zero.
+ BOOST_ASIO_CHECK(*count == 0);
+ }
+}
+
+void sleep_increment(io_context* ioc, int* count)
+{
+ timer t(*ioc, chronons::seconds(2));
+ t.wait();
+
+ if (++(*count) < 3)
+ boost::asio::post(*ioc, bindns::bind(sleep_increment, ioc, count));
+}
+
+void start_sleep_increments(io_context* ioc, int* count)
+{
+ // Give all threads a chance to start.
+ timer t(*ioc, chronons::seconds(2));
+ t.wait();
+
+ // Start the first of three increments.
+ boost::asio::post(*ioc, bindns::bind(sleep_increment, ioc, count));
+}
+
+void throw_exception()
+{
+ throw 1;
+}
+
+void io_context_run(io_context* ioc)
+{
+ ioc->run();
+}
+
+void io_context_test()
+{
+ io_context ioc;
+ int count = 0;
+
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 0;
+ ioc.restart();
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 5);
+
+ count = 0;
+ ioc.restart();
+ executor_work_guard<io_context::executor_type> w = make_work_guard(ioc);
+ boost::asio::post(ioc, bindns::bind(&io_context::stop, &ioc));
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ ioc.run();
+
+ // The only operation executed should have been to stop run().
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+ w.reset();
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 10;
+ ioc.restart();
+ boost::asio::post(ioc, bindns::bind(decrement_to_zero, &ioc, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 10);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+
+ count = 10;
+ ioc.restart();
+ boost::asio::post(ioc, bindns::bind(nested_decrement_to_zero, &ioc, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 10);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+
+ count = 10;
+ ioc.restart();
+ boost::asio::dispatch(ioc,
+ bindns::bind(nested_decrement_to_zero, &ioc, &count));
+
+ // No handlers can be called until run() is called, even though nested
+ // delivery was specifically allowed in the previous call.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 10);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+
+ count = 0;
+ int count2 = 0;
+ ioc.restart();
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ boost::asio::post(ioc, bindns::bind(start_sleep_increments, &ioc, &count));
+ boost::asio::post(ioc, bindns::bind(start_sleep_increments, &ioc, &count2));
+ boost::asio::detail::thread thread1(bindns::bind(io_context_run, &ioc));
+ boost::asio::detail::thread thread2(bindns::bind(io_context_run, &ioc));
+ thread1.join();
+ thread2.join();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 3);
+ BOOST_ASIO_CHECK(count2 == 3);
+
+ count = 10;
+ io_context ioc2;
+ boost::asio::dispatch(ioc, boost::asio::bind_executor(ioc2,
+ bindns::bind(decrement_to_zero, &ioc2, &count)));
+ ioc.restart();
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ ioc.run();
+
+ // No decrement_to_zero handlers can be called until run() is called on the
+ // second io_context object.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 10);
+
+ ioc2.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 0);
+
+ count = 0;
+ int exception_count = 0;
+ ioc.restart();
+ boost::asio::post(ioc, &throw_exception);
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+ boost::asio::post(ioc, &throw_exception);
+ boost::asio::post(ioc, bindns::bind(increment, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(!ioc.stopped());
+ BOOST_ASIO_CHECK(count == 0);
+ BOOST_ASIO_CHECK(exception_count == 0);
+
+ for (;;)
+ {
+ try
+ {
+ ioc.run();
+ break;
+ }
+ catch (int)
+ {
+ ++exception_count;
+ }
+ }
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(ioc.stopped());
+ BOOST_ASIO_CHECK(count == 3);
+ BOOST_ASIO_CHECK(exception_count == 2);
+}
+
+class test_service : public boost::asio::io_context::service
+{
+public:
+ static boost::asio::io_context::id id;
+ test_service(boost::asio::io_context& s)
+ : boost::asio::io_context::service(s) {}
+private:
+ virtual void shutdown_service() {}
+};
+
+boost::asio::io_context::id test_service::id;
+
+void io_context_service_test()
+{
+ boost::asio::io_context ioc1;
+ boost::asio::io_context ioc2;
+ boost::asio::io_context ioc3;
+
+ // Implicit service registration.
+
+ boost::asio::use_service<test_service>(ioc1);
+
+ BOOST_ASIO_CHECK(boost::asio::has_service<test_service>(ioc1));
+
+ test_service* svc1 = new test_service(ioc1);
+ try
+ {
+ boost::asio::add_service(ioc1, svc1);
+ BOOST_ASIO_ERROR("add_service did not throw");
+ }
+ catch (boost::asio::service_already_exists&)
+ {
+ }
+ delete svc1;
+
+ // Explicit service registration.
+
+ test_service* svc2 = new test_service(ioc2);
+ boost::asio::add_service(ioc2, svc2);
+
+ BOOST_ASIO_CHECK(boost::asio::has_service<test_service>(ioc2));
+ BOOST_ASIO_CHECK(&boost::asio::use_service<test_service>(ioc2) == svc2);
+
+ test_service* svc3 = new test_service(ioc2);
+ try
+ {
+ boost::asio::add_service(ioc2, svc3);
+ BOOST_ASIO_ERROR("add_service did not throw");
+ }
+ catch (boost::asio::service_already_exists&)
+ {
+ }
+ delete svc3;
+
+ // Explicit registration with invalid owner.
+
+ test_service* svc4 = new test_service(ioc2);
+ try
+ {
+ boost::asio::add_service(ioc3, svc4);
+ BOOST_ASIO_ERROR("add_service did not throw");
+ }
+ catch (boost::asio::invalid_service_owner&)
+ {
+ }
+ delete svc4;
+
+ BOOST_ASIO_CHECK(!boost::asio::has_service<test_service>(ioc3));
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "io_context",
+ BOOST_ASIO_TEST_CASE(io_context_test)
+ BOOST_ASIO_TEST_CASE(io_context_service_test)
+)
diff --git a/src/boost/libs/asio/test/io_context_strand.cpp b/src/boost/libs/asio/test/io_context_strand.cpp
new file mode 100644
index 000000000..fec4f3765
--- /dev/null
+++ b/src/boost/libs/asio/test/io_context_strand.cpp
@@ -0,0 +1,325 @@
+//
+// io_context_strand.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/io_context_strand.hpp>
+
+#include <sstream>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/detail/thread.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/deadline_timer.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/steady_timer.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+using namespace boost::asio;
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = std;
+#endif
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+typedef deadline_timer timer;
+namespace chronons = boost::posix_time;
+#elif defined(BOOST_ASIO_HAS_CHRONO)
+typedef steady_timer timer;
+namespace chronons = boost::asio::chrono;
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+void increment(int* count)
+{
+ ++(*count);
+}
+
+void increment_without_lock(io_context::strand* s, int* count)
+{
+ BOOST_ASIO_CHECK(!s->running_in_this_thread());
+
+ int original_count = *count;
+
+ dispatch(*s, bindns::bind(increment, count));
+
+ // No other functions are currently executing through the locking dispatcher,
+ // so the previous call to dispatch should have successfully nested.
+ BOOST_ASIO_CHECK(*count == original_count + 1);
+}
+
+void increment_with_lock(io_context::strand* s, int* count)
+{
+ BOOST_ASIO_CHECK(s->running_in_this_thread());
+
+ int original_count = *count;
+
+ dispatch(*s, bindns::bind(increment, count));
+
+ // The current function already holds the strand's lock, so the
+ // previous call to dispatch should have successfully nested.
+ BOOST_ASIO_CHECK(*count == original_count + 1);
+}
+
+void sleep_increment(io_context* ioc, int* count)
+{
+ timer t(*ioc, chronons::seconds(2));
+ t.wait();
+
+ ++(*count);
+}
+
+void increment_by_a(int* count, int a)
+{
+ (*count) += a;
+}
+
+void increment_by_a_b(int* count, int a, int b)
+{
+ (*count) += a + b;
+}
+
+void increment_by_a_b_c(int* count, int a, int b, int c)
+{
+ (*count) += a + b + c;
+}
+
+void increment_by_a_b_c_d(int* count, int a, int b, int c, int d)
+{
+ (*count) += a + b + c + d;
+}
+
+void start_sleep_increments(io_context* ioc, io_context::strand* s, int* count)
+{
+ // Give all threads a chance to start.
+ timer t(*ioc, chronons::seconds(2));
+ t.wait();
+
+ // Start three increments.
+ post(*s, bindns::bind(sleep_increment, ioc, count));
+ post(*s, bindns::bind(sleep_increment, ioc, count));
+ post(*s, bindns::bind(sleep_increment, ioc, count));
+}
+
+void throw_exception()
+{
+ throw 1;
+}
+
+void io_context_run(io_context* ioc)
+{
+ ioc->run();
+}
+
+void strand_test()
+{
+ io_context ioc;
+ io_context::strand s(ioc);
+ int count = 0;
+
+ post(ioc, bindns::bind(increment_without_lock, &s, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 0;
+ ioc.restart();
+ post(s, bindns::bind(increment_with_lock, &s, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 0;
+ ioc.restart();
+ post(ioc, bindns::bind(start_sleep_increments, &ioc, &s, &count));
+ boost::asio::detail::thread thread1(bindns::bind(io_context_run, &ioc));
+ boost::asio::detail::thread thread2(bindns::bind(io_context_run, &ioc));
+
+ // Check all events run one after another even though there are two threads.
+ timer timer1(ioc, chronons::seconds(3));
+ timer1.wait();
+ BOOST_ASIO_CHECK(count == 0);
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.expires_at(timer1.expires_at() + chronons::seconds(2));
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.expires_at(timer1.expiry() + chronons::seconds(2));
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.wait();
+ BOOST_ASIO_CHECK(count == 1);
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.expires_at(timer1.expires_at() + chronons::seconds(2));
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.expires_at(timer1.expiry() + chronons::seconds(2));
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.wait();
+ BOOST_ASIO_CHECK(count == 2);
+
+ thread1.join();
+ thread2.join();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 3);
+
+ count = 0;
+ int exception_count = 0;
+ ioc.restart();
+ post(s, throw_exception);
+ post(s, bindns::bind(increment, &count));
+ post(s, bindns::bind(increment, &count));
+ post(s, throw_exception);
+ post(s, bindns::bind(increment, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+ BOOST_ASIO_CHECK(exception_count == 0);
+
+ for (;;)
+ {
+ try
+ {
+ ioc.run();
+ break;
+ }
+ catch (int)
+ {
+ ++exception_count;
+ }
+ }
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 3);
+ BOOST_ASIO_CHECK(exception_count == 2);
+
+ count = 0;
+ ioc.restart();
+
+ // Check for clean shutdown when handlers posted through an orphaned strand
+ // are abandoned.
+ {
+ io_context::strand s2(ioc);
+ post(s2, bindns::bind(increment, &count));
+ post(s2, bindns::bind(increment, &count));
+ post(s2, bindns::bind(increment, &count));
+ }
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+}
+
+void strand_wrap_test()
+{
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ io_context ioc;
+ io_context::strand s(ioc);
+ int count = 0;
+
+ s.wrap(bindns::bind(increment, &count))();
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ ioc.run();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 0;
+ s.wrap(increment)(&count);
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ ioc.run();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 0;
+ s.wrap(increment_by_a)(&count, 1);
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ ioc.run();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 0;
+ s.wrap(increment_by_a_b)(&count, 1, 2);
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ ioc.run();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 3);
+
+ count = 0;
+ s.wrap(increment_by_a_b_c)(&count, 1, 2, 3);
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ ioc.run();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 6);
+
+ count = 0;
+ s.wrap(increment_by_a_b_c_d)(&count, 1, 2, 3, 4);
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ ioc.run();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 10);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "strand",
+ BOOST_ASIO_TEST_CASE(strand_test)
+ BOOST_ASIO_TEST_CASE(strand_wrap_test)
+)
diff --git a/src/boost/libs/asio/test/ip/address.cpp b/src/boost/libs/asio/test/ip/address.cpp
new file mode 100644
index 000000000..c4fc82267
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/address.cpp
@@ -0,0 +1,144 @@
+//
+// address.cpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/address.hpp>
+
+#include "../unit_test.hpp"
+#include <sstream>
+
+//------------------------------------------------------------------------------
+
+// ip_address_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::address compile and link correctly. Runtime failures are ignored.
+
+namespace ip_address_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ boost::system::error_code ec;
+
+ // address constructors.
+
+ ip::address addr1;
+ const ip::address_v4 const_addr_v4;
+ ip::address addr2(const_addr_v4);
+ const ip::address_v6 const_addr_v6;
+ ip::address addr3(const_addr_v6);
+
+ // address functions.
+
+ bool b = addr1.is_v4();
+ (void)b;
+
+ b = addr1.is_v6();
+ (void)b;
+
+ b = addr1.is_loopback();
+ (void)b;
+
+ b = addr1.is_unspecified();
+ (void)b;
+
+ b = addr1.is_multicast();
+ (void)b;
+
+ ip::address_v4 addr_v4_value = addr1.to_v4();
+ (void)addr_v4_value;
+
+ ip::address_v6 addr_v6_value = addr1.to_v6();
+ (void)addr_v6_value;
+
+ std::string string_value = addr1.to_string();
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ string_value = addr1.to_string(ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // address static functions.
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ addr1 = ip::address::from_string("127.0.0.1");
+ addr1 = ip::address::from_string("127.0.0.1", ec);
+ addr1 = ip::address::from_string(string_value);
+ addr1 = ip::address::from_string(string_value, ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // address comparisons.
+
+ b = (addr1 == addr2);
+ (void)b;
+
+ b = (addr1 != addr2);
+ (void)b;
+
+ b = (addr1 < addr2);
+ (void)b;
+
+ b = (addr1 > addr2);
+ (void)b;
+
+ b = (addr1 <= addr2);
+ (void)b;
+
+ b = (addr1 >= addr2);
+ (void)b;
+
+ // address creation functions.
+
+ addr1 = ip::make_address("127.0.0.1");
+ addr1 = ip::make_address("127.0.0.1", ec);
+ addr1 = ip::make_address(string_value);
+ addr1 = ip::make_address(string_value, ec);
+#if defined(BOOST_ASIO_HAS_STRING_VIEW)
+# if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ std::string_view string_view_value("127.0.0.1");
+# elif defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ std::experimental::string_view string_view_value("127.0.0.1");
+# endif // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ addr1 = ip::make_address(string_view_value);
+ addr1 = ip::make_address(string_view_value, ec);
+#endif // defined(BOOST_ASIO_HAS_STRING_VIEW)
+
+ // address I/O.
+
+ std::ostringstream os;
+ os << addr1;
+
+#if !defined(BOOST_NO_STD_WSTREAMBUF)
+ std::wostringstream wos;
+ wos << addr1;
+#endif // !defined(BOOST_NO_STD_WSTREAMBUF)
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_address_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/address",
+ BOOST_ASIO_TEST_CASE(ip_address_compile::test)
+)
diff --git a/src/boost/libs/asio/test/ip/address_v4.cpp b/src/boost/libs/asio/test/ip/address_v4.cpp
new file mode 100644
index 000000000..abe0c34a4
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/address_v4.cpp
@@ -0,0 +1,324 @@
+//
+// address_v4.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/address_v4.hpp>
+
+#include "../unit_test.hpp"
+#include <sstream>
+
+//------------------------------------------------------------------------------
+
+// ip_address_v4_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::address_v4 compile and link correctly. Runtime failures are ignored.
+
+namespace ip_address_v4_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ boost::system::error_code ec;
+
+ // address_v4 constructors.
+
+ ip::address_v4 addr1;
+ const ip::address_v4::bytes_type const_bytes_value = { { 127, 0, 0, 1 } };
+ ip::address_v4 addr2(const_bytes_value);
+ const unsigned long const_ulong_value = 0x7F000001;
+ ip::address_v4 addr3(const_ulong_value);
+
+ // address_v4 functions.
+
+ bool b = addr1.is_loopback();
+ (void)b;
+
+ b = addr1.is_unspecified();
+ (void)b;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ b = addr1.is_class_a();
+ (void)b;
+
+ b = addr1.is_class_b();
+ (void)b;
+
+ b = addr1.is_class_c();
+ (void)b;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ b = addr1.is_multicast();
+ (void)b;
+
+ ip::address_v4::bytes_type bytes_value = addr1.to_bytes();
+ (void)bytes_value;
+
+ ip::address_v4::uint_type uint_value = addr1.to_uint();
+ (void)uint_value;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ unsigned long ulong_value = addr1.to_ulong();
+ (void)ulong_value;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ std::string string_value = addr1.to_string();
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ string_value = addr1.to_string(ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // address_v4 static functions.
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ addr1 = ip::address_v4::from_string("127.0.0.1");
+ addr1 = ip::address_v4::from_string("127.0.0.1", ec);
+ addr1 = ip::address_v4::from_string(string_value);
+ addr1 = ip::address_v4::from_string(string_value, ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ addr1 = ip::address_v4::any();
+
+ addr1 = ip::address_v4::loopback();
+
+ addr1 = ip::address_v4::broadcast();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ addr1 = ip::address_v4::broadcast(addr2, addr3);
+
+ addr1 = ip::address_v4::netmask(addr2);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // address_v4 comparisons.
+
+ b = (addr1 == addr2);
+ (void)b;
+
+ b = (addr1 != addr2);
+ (void)b;
+
+ b = (addr1 < addr2);
+ (void)b;
+
+ b = (addr1 > addr2);
+ (void)b;
+
+ b = (addr1 <= addr2);
+ (void)b;
+
+ b = (addr1 >= addr2);
+ (void)b;
+
+ // address_v4 creation functions.
+
+ addr1 = ip::make_address_v4(const_bytes_value);
+ addr1 = ip::make_address_v4(const_ulong_value);
+ addr1 = ip::make_address_v4("127.0.0.1");
+ addr1 = ip::make_address_v4("127.0.0.1", ec);
+ addr1 = ip::make_address_v4(string_value);
+ addr1 = ip::make_address_v4(string_value, ec);
+#if defined(BOOST_ASIO_HAS_STRING_VIEW)
+# if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ std::string_view string_view_value("127.0.0.1");
+# elif defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ std::experimental::string_view string_view_value("127.0.0.1");
+# endif // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ addr1 = ip::make_address_v4(string_view_value);
+ addr1 = ip::make_address_v4(string_view_value, ec);
+#endif // defined(BOOST_ASIO_HAS_STRING_VIEW)
+
+ // address_v4 I/O.
+
+ std::ostringstream os;
+ os << addr1;
+
+#if !defined(BOOST_NO_STD_WSTREAMBUF)
+ std::wostringstream wos;
+ wos << addr1;
+#endif // !defined(BOOST_NO_STD_WSTREAMBUF)
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_address_v4_compile
+
+//------------------------------------------------------------------------------
+
+// ip_address_v4_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that the various public member functions meet the
+// necessary postconditions.
+
+namespace ip_address_v4_runtime {
+
+void test()
+{
+ using boost::asio::ip::address_v4;
+
+ address_v4 a1;
+ BOOST_ASIO_CHECK(a1.to_bytes()[0] == 0);
+ BOOST_ASIO_CHECK(a1.to_bytes()[1] == 0);
+ BOOST_ASIO_CHECK(a1.to_bytes()[2] == 0);
+ BOOST_ASIO_CHECK(a1.to_bytes()[3] == 0);
+ BOOST_ASIO_CHECK(a1.to_uint() == 0);
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(a1.to_ulong() == 0);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ address_v4::bytes_type b1 = {{ 1, 2, 3, 4 }};
+ address_v4 a2(b1);
+ BOOST_ASIO_CHECK(a2.to_bytes()[0] == 1);
+ BOOST_ASIO_CHECK(a2.to_bytes()[1] == 2);
+ BOOST_ASIO_CHECK(a2.to_bytes()[2] == 3);
+ BOOST_ASIO_CHECK(a2.to_bytes()[3] == 4);
+ BOOST_ASIO_CHECK(((a2.to_uint() >> 24) & 0xFF) == b1[0]);
+ BOOST_ASIO_CHECK(((a2.to_uint() >> 16) & 0xFF) == b1[1]);
+ BOOST_ASIO_CHECK(((a2.to_uint() >> 8) & 0xFF) == b1[2]);
+ BOOST_ASIO_CHECK((a2.to_uint() & 0xFF) == b1[3]);
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(((a2.to_ulong() >> 24) & 0xFF) == b1[0]);
+ BOOST_ASIO_CHECK(((a2.to_ulong() >> 16) & 0xFF) == b1[1]);
+ BOOST_ASIO_CHECK(((a2.to_ulong() >> 8) & 0xFF) == b1[2]);
+ BOOST_ASIO_CHECK((a2.to_ulong() & 0xFF) == b1[3]);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ address_v4 a3(0x01020304);
+ BOOST_ASIO_CHECK(a3.to_bytes()[0] == 1);
+ BOOST_ASIO_CHECK(a3.to_bytes()[1] == 2);
+ BOOST_ASIO_CHECK(a3.to_bytes()[2] == 3);
+ BOOST_ASIO_CHECK(a3.to_bytes()[3] == 4);
+ BOOST_ASIO_CHECK(a3.to_uint() == 0x01020304);
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(a3.to_ulong() == 0x01020304);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ BOOST_ASIO_CHECK(address_v4(0x7F000001).is_loopback());
+ BOOST_ASIO_CHECK(address_v4(0x7F000002).is_loopback());
+ BOOST_ASIO_CHECK(!address_v4(0x00000000).is_loopback());
+ BOOST_ASIO_CHECK(!address_v4(0x01020304).is_loopback());
+
+ BOOST_ASIO_CHECK(address_v4(0x00000000).is_unspecified());
+ BOOST_ASIO_CHECK(!address_v4(0x7F000001).is_unspecified());
+ BOOST_ASIO_CHECK(!address_v4(0x01020304).is_unspecified());
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(address_v4(0x01000000).is_class_a());
+ BOOST_ASIO_CHECK(address_v4(0x7F000000).is_class_a());
+ BOOST_ASIO_CHECK(!address_v4(0x80000000).is_class_a());
+ BOOST_ASIO_CHECK(!address_v4(0xBFFF0000).is_class_a());
+ BOOST_ASIO_CHECK(!address_v4(0xC0000000).is_class_a());
+ BOOST_ASIO_CHECK(!address_v4(0xDFFFFF00).is_class_a());
+ BOOST_ASIO_CHECK(!address_v4(0xE0000000).is_class_a());
+ BOOST_ASIO_CHECK(!address_v4(0xEFFFFFFF).is_class_a());
+ BOOST_ASIO_CHECK(!address_v4(0xF0000000).is_class_a());
+ BOOST_ASIO_CHECK(!address_v4(0xFFFFFFFF).is_class_a());
+
+ BOOST_ASIO_CHECK(!address_v4(0x01000000).is_class_b());
+ BOOST_ASIO_CHECK(!address_v4(0x7F000000).is_class_b());
+ BOOST_ASIO_CHECK(address_v4(0x80000000).is_class_b());
+ BOOST_ASIO_CHECK(address_v4(0xBFFF0000).is_class_b());
+ BOOST_ASIO_CHECK(!address_v4(0xC0000000).is_class_b());
+ BOOST_ASIO_CHECK(!address_v4(0xDFFFFF00).is_class_b());
+ BOOST_ASIO_CHECK(!address_v4(0xE0000000).is_class_b());
+ BOOST_ASIO_CHECK(!address_v4(0xEFFFFFFF).is_class_b());
+ BOOST_ASIO_CHECK(!address_v4(0xF0000000).is_class_b());
+ BOOST_ASIO_CHECK(!address_v4(0xFFFFFFFF).is_class_b());
+
+ BOOST_ASIO_CHECK(!address_v4(0x01000000).is_class_c());
+ BOOST_ASIO_CHECK(!address_v4(0x7F000000).is_class_c());
+ BOOST_ASIO_CHECK(!address_v4(0x80000000).is_class_c());
+ BOOST_ASIO_CHECK(!address_v4(0xBFFF0000).is_class_c());
+ BOOST_ASIO_CHECK(address_v4(0xC0000000).is_class_c());
+ BOOST_ASIO_CHECK(address_v4(0xDFFFFF00).is_class_c());
+ BOOST_ASIO_CHECK(!address_v4(0xE0000000).is_class_c());
+ BOOST_ASIO_CHECK(!address_v4(0xEFFFFFFF).is_class_c());
+ BOOST_ASIO_CHECK(!address_v4(0xF0000000).is_class_c());
+ BOOST_ASIO_CHECK(!address_v4(0xFFFFFFFF).is_class_c());
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ BOOST_ASIO_CHECK(!address_v4(0x01000000).is_multicast());
+ BOOST_ASIO_CHECK(!address_v4(0x7F000000).is_multicast());
+ BOOST_ASIO_CHECK(!address_v4(0x80000000).is_multicast());
+ BOOST_ASIO_CHECK(!address_v4(0xBFFF0000).is_multicast());
+ BOOST_ASIO_CHECK(!address_v4(0xC0000000).is_multicast());
+ BOOST_ASIO_CHECK(!address_v4(0xDFFFFF00).is_multicast());
+ BOOST_ASIO_CHECK(address_v4(0xE0000000).is_multicast());
+ BOOST_ASIO_CHECK(address_v4(0xEFFFFFFF).is_multicast());
+ BOOST_ASIO_CHECK(!address_v4(0xF0000000).is_multicast());
+ BOOST_ASIO_CHECK(!address_v4(0xFFFFFFFF).is_multicast());
+
+ address_v4 a4 = address_v4::any();
+ BOOST_ASIO_CHECK(a4.to_bytes()[0] == 0);
+ BOOST_ASIO_CHECK(a4.to_bytes()[1] == 0);
+ BOOST_ASIO_CHECK(a4.to_bytes()[2] == 0);
+ BOOST_ASIO_CHECK(a4.to_bytes()[3] == 0);
+ BOOST_ASIO_CHECK(a4.to_uint() == 0);
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(a4.to_ulong() == 0);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ address_v4 a5 = address_v4::loopback();
+ BOOST_ASIO_CHECK(a5.to_bytes()[0] == 0x7F);
+ BOOST_ASIO_CHECK(a5.to_bytes()[1] == 0);
+ BOOST_ASIO_CHECK(a5.to_bytes()[2] == 0);
+ BOOST_ASIO_CHECK(a5.to_bytes()[3] == 0x01);
+ BOOST_ASIO_CHECK(a5.to_uint() == 0x7F000001);
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(a5.to_ulong() == 0x7F000001);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ address_v4 a6 = address_v4::broadcast();
+ BOOST_ASIO_CHECK(a6.to_bytes()[0] == 0xFF);
+ BOOST_ASIO_CHECK(a6.to_bytes()[1] == 0xFF);
+ BOOST_ASIO_CHECK(a6.to_bytes()[2] == 0xFF);
+ BOOST_ASIO_CHECK(a6.to_bytes()[3] == 0xFF);
+ BOOST_ASIO_CHECK(a6.to_uint() == 0xFFFFFFFF);
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(a6.to_ulong() == 0xFFFFFFFF);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ address_v4 class_a_net(0xFF000000);
+ address_v4 class_b_net(0xFFFF0000);
+ address_v4 class_c_net(0xFFFFFF00);
+ address_v4 other_net(0xFFFFFFFF);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0x01000000)) == class_a_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0x7F000000)) == class_a_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0x80000000)) == class_b_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0xBFFF0000)) == class_b_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0xC0000000)) == class_c_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0xDFFFFF00)) == class_c_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0xE0000000)) == other_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0xEFFFFFFF)) == other_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0xF0000000)) == other_net);
+ BOOST_ASIO_CHECK(address_v4::netmask(address_v4(0xFFFFFFFF)) == other_net);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+}
+
+} // namespace ip_address_v4_runtime
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/address_v4",
+ BOOST_ASIO_TEST_CASE(ip_address_v4_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_address_v4_runtime::test)
+)
diff --git a/src/boost/libs/asio/test/ip/address_v4_iterator.cpp b/src/boost/libs/asio/test/ip/address_v4_iterator.cpp
new file mode 100644
index 000000000..94d847646
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/address_v4_iterator.cpp
@@ -0,0 +1,27 @@
+//
+// address_v4_iterator.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/address_v4_iterator.hpp>
+
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/address_v4_iterator",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/address_v4_range.cpp b/src/boost/libs/asio/test/ip/address_v4_range.cpp
new file mode 100644
index 000000000..1ecaf6d03
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/address_v4_range.cpp
@@ -0,0 +1,27 @@
+//
+// address_v4_range.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/address_v4_range.hpp>
+
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/address_v4_range",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/address_v6.cpp b/src/boost/libs/asio/test/ip/address_v6.cpp
new file mode 100644
index 000000000..7f35071d0
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/address_v6.cpp
@@ -0,0 +1,409 @@
+//
+// address_v6.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/address_v6.hpp>
+
+#include "../unit_test.hpp"
+#include <sstream>
+
+//------------------------------------------------------------------------------
+
+// ip_address_v6_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::address_v6 compile and link correctly. Runtime failures are ignored.
+
+namespace ip_address_v6_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ boost::system::error_code ec;
+
+ // address_v6 constructors.
+
+ ip::address_v6 addr1;
+ const ip::address_v6::bytes_type const_bytes_value = { { 0 } };
+ ip::address_v6 addr2(const_bytes_value);
+
+ // address_v6 functions.
+
+ unsigned long scope_id = addr1.scope_id();
+ addr1.scope_id(scope_id);
+
+ bool b = addr1.is_unspecified();
+ (void)b;
+
+ b = addr1.is_loopback();
+ (void)b;
+
+ b = addr1.is_multicast();
+ (void)b;
+
+ b = addr1.is_link_local();
+ (void)b;
+
+ b = addr1.is_site_local();
+ (void)b;
+
+ b = addr1.is_v4_mapped();
+ (void)b;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ b = addr1.is_v4_compatible();
+ (void)b;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ b = addr1.is_multicast_node_local();
+ (void)b;
+
+ b = addr1.is_multicast_link_local();
+ (void)b;
+
+ b = addr1.is_multicast_site_local();
+ (void)b;
+
+ b = addr1.is_multicast_org_local();
+ (void)b;
+
+ b = addr1.is_multicast_global();
+ (void)b;
+
+ ip::address_v6::bytes_type bytes_value = addr1.to_bytes();
+ (void)bytes_value;
+
+ std::string string_value = addr1.to_string();
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ string_value = addr1.to_string(ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::address_v4 addr3 = addr1.to_v4();
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // address_v6 static functions.
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ addr1 = ip::address_v6::from_string("0::0");
+ addr1 = ip::address_v6::from_string("0::0", ec);
+ addr1 = ip::address_v6::from_string(string_value);
+ addr1 = ip::address_v6::from_string(string_value, ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ addr1 = ip::address_v6::any();
+
+ addr1 = ip::address_v6::loopback();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ addr1 = ip::address_v6::v4_mapped(addr3);
+
+ addr1 = ip::address_v6::v4_compatible(addr3);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ // address_v6 comparisons.
+
+ b = (addr1 == addr2);
+ (void)b;
+
+ b = (addr1 != addr2);
+ (void)b;
+
+ b = (addr1 < addr2);
+ (void)b;
+
+ b = (addr1 > addr2);
+ (void)b;
+
+ b = (addr1 <= addr2);
+ (void)b;
+
+ b = (addr1 >= addr2);
+ (void)b;
+
+ // address_v6 creation functions.
+
+ addr1 = ip::make_address_v6(const_bytes_value, scope_id);
+ addr1 = ip::make_address_v6("0::0");
+ addr1 = ip::make_address_v6("0::0", ec);
+ addr1 = ip::make_address_v6(string_value);
+ addr1 = ip::make_address_v6(string_value, ec);
+#if defined(BOOST_ASIO_HAS_STRING_VIEW)
+# if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ std::string_view string_view_value("0::0");
+# else // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ std::experimental::string_view string_view_value("0::0");
+# endif // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ addr1 = ip::make_address_v6(string_view_value);
+ addr1 = ip::make_address_v6(string_view_value, ec);
+#endif // defined(BOOST_ASIO_HAS_STRING_VIEW)
+
+ // address_v6 IPv4-mapped conversion.
+#if defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::address_v4 addr3;
+#endif // defined(BOOST_ASIO_NO_DEPRECATED)
+ addr1 = ip::make_address_v6(ip::v4_mapped, addr3);
+ addr3 = ip::make_address_v4(ip::v4_mapped, addr1);
+
+ // address_v6 I/O.
+
+ std::ostringstream os;
+ os << addr1;
+
+#if !defined(BOOST_NO_STD_WSTREAMBUF)
+ std::wostringstream wos;
+ wos << addr1;
+#endif // !defined(BOOST_NO_STD_WSTREAMBUF)
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_address_v6_compile
+
+//------------------------------------------------------------------------------
+
+// ip_address_v6_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that the various public member functions meet the
+// necessary postconditions.
+
+namespace ip_address_v6_runtime {
+
+void test()
+{
+ using boost::asio::ip::address_v6;
+
+ address_v6 a1;
+ BOOST_ASIO_CHECK(a1.is_unspecified());
+ BOOST_ASIO_CHECK(a1.scope_id() == 0);
+
+ address_v6::bytes_type b1 = {{ 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }};
+ address_v6 a2(b1, 12345);
+ BOOST_ASIO_CHECK(a2.to_bytes()[0] == 1);
+ BOOST_ASIO_CHECK(a2.to_bytes()[1] == 2);
+ BOOST_ASIO_CHECK(a2.to_bytes()[2] == 3);
+ BOOST_ASIO_CHECK(a2.to_bytes()[3] == 4);
+ BOOST_ASIO_CHECK(a2.to_bytes()[4] == 5);
+ BOOST_ASIO_CHECK(a2.to_bytes()[5] == 6);
+ BOOST_ASIO_CHECK(a2.to_bytes()[6] == 7);
+ BOOST_ASIO_CHECK(a2.to_bytes()[7] == 8);
+ BOOST_ASIO_CHECK(a2.to_bytes()[8] == 9);
+ BOOST_ASIO_CHECK(a2.to_bytes()[9] == 10);
+ BOOST_ASIO_CHECK(a2.to_bytes()[10] == 11);
+ BOOST_ASIO_CHECK(a2.to_bytes()[11] == 12);
+ BOOST_ASIO_CHECK(a2.to_bytes()[12] == 13);
+ BOOST_ASIO_CHECK(a2.to_bytes()[13] == 14);
+ BOOST_ASIO_CHECK(a2.to_bytes()[14] == 15);
+ BOOST_ASIO_CHECK(a2.to_bytes()[15] == 16);
+ BOOST_ASIO_CHECK(a2.scope_id() == 12345);
+
+ address_v6 a3;
+ a3.scope_id(12345);
+ BOOST_ASIO_CHECK(a3.scope_id() == 12345);
+
+ address_v6 unspecified_address;
+ address_v6::bytes_type loopback_bytes = {{ 0 }};
+ loopback_bytes[15] = 1;
+ address_v6 loopback_address(loopback_bytes);
+ address_v6::bytes_type link_local_bytes = {{ 0xFE, 0x80, 1 }};
+ address_v6 link_local_address(link_local_bytes);
+ address_v6::bytes_type site_local_bytes = {{ 0xFE, 0xC0, 1 }};
+ address_v6 site_local_address(site_local_bytes);
+ address_v6::bytes_type v4_mapped_bytes = {{ 0 }};
+ v4_mapped_bytes[10] = 0xFF, v4_mapped_bytes[11] = 0xFF;
+ v4_mapped_bytes[12] = 1, v4_mapped_bytes[13] = 2;
+ v4_mapped_bytes[14] = 3, v4_mapped_bytes[15] = 4;
+ address_v6 v4_mapped_address(v4_mapped_bytes);
+ address_v6::bytes_type v4_compat_bytes = {{ 0 }};
+ v4_compat_bytes[12] = 1, v4_compat_bytes[13] = 2;
+ v4_compat_bytes[14] = 3, v4_compat_bytes[15] = 4;
+ address_v6 v4_compat_address(v4_compat_bytes);
+ address_v6::bytes_type mcast_global_bytes = {{ 0xFF, 0x0E, 1 }};
+ address_v6 mcast_global_address(mcast_global_bytes);
+ address_v6::bytes_type mcast_link_local_bytes = {{ 0xFF, 0x02, 1 }};
+ address_v6 mcast_link_local_address(mcast_link_local_bytes);
+ address_v6::bytes_type mcast_node_local_bytes = {{ 0xFF, 0x01, 1 }};
+ address_v6 mcast_node_local_address(mcast_node_local_bytes);
+ address_v6::bytes_type mcast_org_local_bytes = {{ 0xFF, 0x08, 1 }};
+ address_v6 mcast_org_local_address(mcast_org_local_bytes);
+ address_v6::bytes_type mcast_site_local_bytes = {{ 0xFF, 0x05, 1 }};
+ address_v6 mcast_site_local_address(mcast_site_local_bytes);
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_loopback());
+ BOOST_ASIO_CHECK(loopback_address.is_loopback());
+ BOOST_ASIO_CHECK(!link_local_address.is_loopback());
+ BOOST_ASIO_CHECK(!site_local_address.is_loopback());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_loopback());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_loopback());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_loopback());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_loopback());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_loopback());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_loopback());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_loopback());
+
+ BOOST_ASIO_CHECK(unspecified_address.is_unspecified());
+ BOOST_ASIO_CHECK(!loopback_address.is_unspecified());
+ BOOST_ASIO_CHECK(!link_local_address.is_unspecified());
+ BOOST_ASIO_CHECK(!site_local_address.is_unspecified());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_unspecified());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_unspecified());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_unspecified());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_unspecified());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_unspecified());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_unspecified());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_unspecified());
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_link_local());
+ BOOST_ASIO_CHECK(!loopback_address.is_link_local());
+ BOOST_ASIO_CHECK(link_local_address.is_link_local());
+ BOOST_ASIO_CHECK(!site_local_address.is_link_local());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_link_local());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_link_local());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_link_local());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_link_local());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_link_local());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_link_local());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_link_local());
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_site_local());
+ BOOST_ASIO_CHECK(!loopback_address.is_site_local());
+ BOOST_ASIO_CHECK(!link_local_address.is_site_local());
+ BOOST_ASIO_CHECK(site_local_address.is_site_local());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_site_local());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_site_local());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_site_local());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_site_local());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_site_local());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_site_local());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_site_local());
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!loopback_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!link_local_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!site_local_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(v4_mapped_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_v4_mapped());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_v4_mapped());
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ BOOST_ASIO_CHECK(!unspecified_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!loopback_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!link_local_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!site_local_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(v4_compat_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_v4_compatible());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_v4_compatible());
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_multicast());
+ BOOST_ASIO_CHECK(!loopback_address.is_multicast());
+ BOOST_ASIO_CHECK(!link_local_address.is_multicast());
+ BOOST_ASIO_CHECK(!site_local_address.is_multicast());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_multicast());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_multicast());
+ BOOST_ASIO_CHECK(mcast_global_address.is_multicast());
+ BOOST_ASIO_CHECK(mcast_link_local_address.is_multicast());
+ BOOST_ASIO_CHECK(mcast_node_local_address.is_multicast());
+ BOOST_ASIO_CHECK(mcast_org_local_address.is_multicast());
+ BOOST_ASIO_CHECK(mcast_site_local_address.is_multicast());
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!loopback_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!link_local_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!site_local_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_multicast_global());
+ BOOST_ASIO_CHECK(mcast_global_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_multicast_global());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_multicast_global());
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!loopback_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!link_local_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!site_local_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(mcast_link_local_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_multicast_link_local());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_multicast_link_local());
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!loopback_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!link_local_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!site_local_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(mcast_node_local_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_multicast_node_local());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_multicast_node_local());
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!loopback_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!link_local_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!site_local_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(mcast_org_local_address.is_multicast_org_local());
+ BOOST_ASIO_CHECK(!mcast_site_local_address.is_multicast_org_local());
+
+ BOOST_ASIO_CHECK(!unspecified_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!loopback_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!link_local_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!site_local_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!v4_mapped_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!v4_compat_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!mcast_global_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!mcast_link_local_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!mcast_node_local_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(!mcast_org_local_address.is_multicast_site_local());
+ BOOST_ASIO_CHECK(mcast_site_local_address.is_multicast_site_local());
+
+ BOOST_ASIO_CHECK(address_v6::loopback().is_loopback());
+}
+
+} // namespace ip_address_v6_runtime
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/address_v6",
+ BOOST_ASIO_TEST_CASE(ip_address_v6_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_address_v6_runtime::test)
+)
diff --git a/src/boost/libs/asio/test/ip/address_v6_iterator.cpp b/src/boost/libs/asio/test/ip/address_v6_iterator.cpp
new file mode 100644
index 000000000..3c0ef1a22
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/address_v6_iterator.cpp
@@ -0,0 +1,27 @@
+//
+// address_v6_iterator.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/address_v6_iterator.hpp>
+
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/address_v6_iterator",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/address_v6_range.cpp b/src/boost/libs/asio/test/ip/address_v6_range.cpp
new file mode 100644
index 000000000..b5210031c
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/address_v6_range.cpp
@@ -0,0 +1,27 @@
+//
+// address_v6_range.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/address_v6_range.hpp>
+
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/address_v6_range",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/basic_endpoint.cpp b/src/boost/libs/asio/test/ip/basic_endpoint.cpp
new file mode 100644
index 000000000..f678e74be
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/basic_endpoint.cpp
@@ -0,0 +1,25 @@
+//
+// basic_endpoint.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/basic_endpoint.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/basic_endpoint",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/basic_resolver.cpp b/src/boost/libs/asio/test/ip/basic_resolver.cpp
new file mode 100644
index 000000000..ae194bb8e
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/basic_resolver.cpp
@@ -0,0 +1,25 @@
+//
+// basic_resolver.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/basic_resolver.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/basic_resolver",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/basic_resolver_entry.cpp b/src/boost/libs/asio/test/ip/basic_resolver_entry.cpp
new file mode 100644
index 000000000..942a4e8e1
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/basic_resolver_entry.cpp
@@ -0,0 +1,25 @@
+//
+// basic_resolver_entry.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/basic_resolver_entry.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/basic_resolver_entry",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/basic_resolver_iterator.cpp b/src/boost/libs/asio/test/ip/basic_resolver_iterator.cpp
new file mode 100644
index 000000000..da15f5682
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/basic_resolver_iterator.cpp
@@ -0,0 +1,25 @@
+//
+// basic_resolver_iterator.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/basic_resolver_iterator",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/basic_resolver_query.cpp b/src/boost/libs/asio/test/ip/basic_resolver_query.cpp
new file mode 100644
index 000000000..59a26caf4
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/basic_resolver_query.cpp
@@ -0,0 +1,25 @@
+//
+// basic_resolver_query.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/basic_resolver_query.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/basic_resolver_query",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/host_name.cpp b/src/boost/libs/asio/test/ip/host_name.cpp
new file mode 100644
index 000000000..edeeb448d
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/host_name.cpp
@@ -0,0 +1,55 @@
+//
+// host_name.cpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/host_name.hpp>
+
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// ip_host_name_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all host_name functions compile and link
+// correctly. Runtime failures are ignored.
+
+namespace ip_host_name_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ boost::system::error_code ec;
+
+ std::string host_name = ip::host_name();
+ std::string host_name2 = ip::host_name(ec);
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_host_name_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/host_name",
+ BOOST_ASIO_TEST_CASE(ip_host_name_compile::test)
+)
diff --git a/src/boost/libs/asio/test/ip/icmp.cpp b/src/boost/libs/asio/test/ip/icmp.cpp
new file mode 100644
index 000000000..2dd9e331a
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/icmp.cpp
@@ -0,0 +1,577 @@
+//
+// icmp.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/icmp.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/placeholders.hpp>
+#include "../unit_test.hpp"
+#include "../archetypes/async_result.hpp"
+#include "../archetypes/gettable_socket_option.hpp"
+#include "../archetypes/io_control_command.hpp"
+#include "../archetypes/settable_socket_option.hpp"
+
+//------------------------------------------------------------------------------
+
+// ip_icmp_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::icmp::socket compile and link correctly. Runtime failures are ignored.
+
+namespace ip_icmp_socket_compile {
+
+struct connect_handler
+{
+ connect_handler() {}
+ void operator()(const boost::system::error_code&) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ connect_handler(connect_handler&&) {}
+private:
+ connect_handler(const connect_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct send_handler
+{
+ send_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ send_handler(send_handler&&) {}
+private:
+ send_handler(const send_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct receive_handler
+{
+ receive_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ receive_handler(receive_handler&&) {}
+private:
+ receive_handler(const receive_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ socket_base::message_flags in_flags = 0;
+ archetypes::settable_socket_option<void> settable_socket_option1;
+ archetypes::settable_socket_option<int> settable_socket_option2;
+ archetypes::settable_socket_option<double> settable_socket_option3;
+ archetypes::gettable_socket_option<void> gettable_socket_option1;
+ archetypes::gettable_socket_option<int> gettable_socket_option2;
+ archetypes::gettable_socket_option<double> gettable_socket_option3;
+ archetypes::io_control_command io_control_command;
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_datagram_socket constructors.
+
+ ip::icmp::socket socket1(ioc);
+ ip::icmp::socket socket2(ioc, ip::icmp::v4());
+ ip::icmp::socket socket3(ioc, ip::icmp::v6());
+ ip::icmp::socket socket4(ioc, ip::icmp::endpoint(ip::icmp::v4(), 0));
+ ip::icmp::socket socket5(ioc, ip::icmp::endpoint(ip::icmp::v6(), 0));
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::icmp::socket::native_handle_type native_socket1
+ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ ip::icmp::socket socket6(ioc, ip::icmp::v4(), native_socket1);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ ip::icmp::socket socket7(ioc_ex);
+ ip::icmp::socket socket8(ioc_ex, ip::icmp::v4());
+ ip::icmp::socket socket9(ioc_ex, ip::icmp::v6());
+ ip::icmp::socket socket10(ioc_ex, ip::icmp::endpoint(ip::icmp::v4(), 0));
+ ip::icmp::socket socket11(ioc_ex, ip::icmp::endpoint(ip::icmp::v6(), 0));
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::icmp::socket::native_handle_type native_socket2
+ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ ip::icmp::socket socket12(ioc_ex, ip::icmp::v4(), native_socket2);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ ip::icmp::socket socket13(std::move(socket6));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_datagram_socket operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ socket1 = ip::icmp::socket(ioc);
+ socket1 = std::move(socket2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ ip::icmp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ ip::icmp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ const ip::icmp::socket& socket14 = socket1;
+ const ip::icmp::socket::lowest_layer_type& lowest_layer2
+ = socket14.lowest_layer();
+ (void)lowest_layer2;
+
+ socket1.open(ip::icmp::v4());
+ socket1.open(ip::icmp::v6());
+ socket1.open(ip::icmp::v4(), ec);
+ socket1.open(ip::icmp::v6(), ec);
+
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::icmp::socket::native_handle_type native_socket3
+ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ socket1.assign(ip::icmp::v4(), native_socket3);
+ ip::icmp::socket::native_handle_type native_socket4
+ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ socket1.assign(ip::icmp::v4(), native_socket4, ec);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ socket1.release();
+ socket1.release(ec);
+
+ ip::icmp::socket::native_handle_type native_socket5
+ = socket1.native_handle();
+ (void)native_socket5;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(ip::icmp::endpoint(ip::icmp::v4(), 0));
+ socket1.bind(ip::icmp::endpoint(ip::icmp::v6(), 0));
+ socket1.bind(ip::icmp::endpoint(ip::icmp::v4(), 0), ec);
+ socket1.bind(ip::icmp::endpoint(ip::icmp::v6(), 0), ec);
+
+ socket1.connect(ip::icmp::endpoint(ip::icmp::v4(), 0));
+ socket1.connect(ip::icmp::endpoint(ip::icmp::v6(), 0));
+ socket1.connect(ip::icmp::endpoint(ip::icmp::v4(), 0), ec);
+ socket1.connect(ip::icmp::endpoint(ip::icmp::v6(), 0), ec);
+
+ socket1.async_connect(ip::icmp::endpoint(ip::icmp::v4(), 0),
+ connect_handler());
+ socket1.async_connect(ip::icmp::endpoint(ip::icmp::v6(), 0),
+ connect_handler());
+ int i1 = socket1.async_connect(ip::icmp::endpoint(ip::icmp::v4(), 0), lazy);
+ (void)i1;
+ int i2 = socket1.async_connect(ip::icmp::endpoint(ip::icmp::v6(), 0), lazy);
+ (void)i2;
+
+ socket1.set_option(settable_socket_option1);
+ socket1.set_option(settable_socket_option1, ec);
+ socket1.set_option(settable_socket_option2);
+ socket1.set_option(settable_socket_option2, ec);
+ socket1.set_option(settable_socket_option3);
+ socket1.set_option(settable_socket_option3, ec);
+
+ socket1.get_option(gettable_socket_option1);
+ socket1.get_option(gettable_socket_option1, ec);
+ socket1.get_option(gettable_socket_option2);
+ socket1.get_option(gettable_socket_option2, ec);
+ socket1.get_option(gettable_socket_option3);
+ socket1.get_option(gettable_socket_option3, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ bool non_blocking1 = socket1.non_blocking();
+ (void)non_blocking1;
+ socket1.non_blocking(true);
+ socket1.non_blocking(false, ec);
+
+ bool non_blocking2 = socket1.native_non_blocking();
+ (void)non_blocking2;
+ socket1.native_non_blocking(true);
+ socket1.native_non_blocking(false, ec);
+
+ ip::icmp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ ip::icmp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ ip::icmp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ ip::icmp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ // basic_datagram_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer));
+ socket1.send(buffer(const_char_buffer));
+ socket1.send(null_buffers());
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), send_handler());
+ socket1.async_send(buffer(const_char_buffer), send_handler());
+ socket1.async_send(null_buffers(), send_handler());
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler());
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler());
+ socket1.async_send(null_buffers(), in_flags, send_handler());
+ int i3 = socket1.async_send(buffer(mutable_char_buffer), lazy);
+ (void)i3;
+ int i4 = socket1.async_send(buffer(const_char_buffer), lazy);
+ (void)i4;
+ int i5 = socket1.async_send(null_buffers(), lazy);
+ (void)i5;
+ int i6 = socket1.async_send(buffer(mutable_char_buffer), in_flags, lazy);
+ (void)i6;
+ int i7 = socket1.async_send(buffer(const_char_buffer), in_flags, lazy);
+ (void)i7;
+ int i8 = socket1.async_send(null_buffers(), in_flags, lazy);
+ (void)i8;
+
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0));
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0));
+ socket1.send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0));
+ socket1.send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0));
+ socket1.send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v4(), 0));
+ socket1.send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v6(), 0));
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags);
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags);
+ socket1.send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags);
+ socket1.send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags);
+ socket1.send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags);
+ socket1.send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags);
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, ec);
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, ec);
+ socket1.send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, ec);
+ socket1.send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, ec);
+ socket1.send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, ec);
+ socket1.send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, ec);
+
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), send_handler());
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), send_handler());
+ socket1.async_send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), send_handler());
+ socket1.async_send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), send_handler());
+ socket1.async_send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), send_handler());
+ socket1.async_send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), send_handler());
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, send_handler());
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, send_handler());
+ socket1.async_send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, send_handler());
+ socket1.async_send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, send_handler());
+ socket1.async_send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, send_handler());
+ socket1.async_send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, send_handler());
+ int i9 = socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), lazy);
+ (void)i9;
+ int i10 = socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), lazy);
+ (void)i10;
+ int i11 = socket1.async_send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), lazy);
+ (void)i11;
+ int i12 = socket1.async_send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), lazy);
+ (void)i12;
+ int i13 = socket1.async_send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), lazy);
+ (void)i13;
+ int i14 = socket1.async_send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), lazy);
+ (void)i14;
+ int i15 = socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, lazy);
+ (void)i15;
+ int i16 = socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, lazy);
+ (void)i16;
+ int i17 = socket1.async_send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, lazy);
+ (void)i17;
+ int i18 = socket1.async_send_to(buffer(const_char_buffer),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, lazy);
+ (void)i18;
+ int i19 = socket1.async_send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v4(), 0), in_flags, lazy);
+ (void)i19;
+ int i20 = socket1.async_send_to(null_buffers(),
+ ip::icmp::endpoint(ip::icmp::v6(), 0), in_flags, lazy);
+ (void)i20;
+
+ socket1.receive(buffer(mutable_char_buffer));
+ socket1.receive(null_buffers());
+ socket1.receive(buffer(mutable_char_buffer), in_flags);
+ socket1.receive(null_buffers(), in_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.receive(null_buffers(), in_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), receive_handler());
+ socket1.async_receive(null_buffers(), receive_handler());
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ receive_handler());
+ socket1.async_receive(null_buffers(), in_flags, receive_handler());
+ int i21 = socket1.async_receive(buffer(mutable_char_buffer), lazy);
+ (void)i21;
+ int i22 = socket1.async_receive(null_buffers(), lazy);
+ (void)i22;
+ int i23 = socket1.async_receive(buffer(mutable_char_buffer),
+ in_flags, lazy);
+ (void)i23;
+ int i24 = socket1.async_receive(null_buffers(), in_flags, lazy);
+ (void)i24;
+
+ ip::icmp::endpoint endpoint;
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint);
+ socket1.receive_from(null_buffers(), endpoint);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags);
+ socket1.receive_from(null_buffers(), endpoint, in_flags);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags, ec);
+ socket1.receive_from(null_buffers(), endpoint, in_flags, ec);
+
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, receive_handler());
+ socket1.async_receive_from(null_buffers(),
+ endpoint, receive_handler());
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, in_flags, receive_handler());
+ socket1.async_receive_from(null_buffers(),
+ endpoint, in_flags, receive_handler());
+ int i25 = socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, lazy);
+ (void)i25;
+ int i26 = socket1.async_receive_from(null_buffers(),
+ endpoint, lazy);
+ (void)i26;
+ int i27 = socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, in_flags, lazy);
+ (void)i27;
+ int i28 = socket1.async_receive_from(null_buffers(),
+ endpoint, in_flags, lazy);
+ (void)i28;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_icmp_socket_compile
+
+//------------------------------------------------------------------------------
+
+// ip_icmp_resolver_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::icmp::resolver compile and link correctly. Runtime failures are ignored.
+
+namespace ip_icmp_resolver_compile {
+
+struct resolve_handler
+{
+ resolve_handler() {}
+ void operator()(const boost::system::error_code&,
+ boost::asio::ip::icmp::resolver::results_type) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ resolve_handler(resolve_handler&&) {}
+private:
+ resolve_handler(const resolve_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::icmp::resolver::query q(ip::icmp::v4(), "localhost", "0");
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::icmp::endpoint e(ip::address_v4::loopback(), 0);
+
+ // basic_resolver constructors.
+
+ ip::icmp::resolver resolver(ioc);
+ ip::icmp::resolver resolver2(ioc_ex);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ ip::icmp::resolver resolver3(std::move(resolver));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_resolver operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ resolver = ip::icmp::resolver(ioc);
+ resolver = std::move(resolver3);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ ip::icmp::resolver::executor_type ex = resolver.get_executor();
+ (void)ex;
+
+ // basic_resolver functions.
+
+ resolver.cancel();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::icmp::resolver::results_type results1 = resolver.resolve(q);
+ (void)results1;
+
+ ip::icmp::resolver::results_type results2 = resolver.resolve(q, ec);
+ (void)results2;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ ip::icmp::resolver::results_type results3 = resolver.resolve("", "");
+ (void)results3;
+
+ ip::icmp::resolver::results_type results4 = resolver.resolve("", "", ec);
+ (void)results4;
+
+ ip::icmp::resolver::results_type results5 =
+ resolver.resolve("", "", ip::icmp::resolver::flags());
+ (void)results5;
+
+ ip::icmp::resolver::results_type results6 =
+ resolver.resolve("", "", ip::icmp::resolver::flags(), ec);
+ (void)results6;
+
+ ip::icmp::resolver::results_type results7 =
+ resolver.resolve(ip::icmp::v4(), "", "");
+ (void)results7;
+
+ ip::icmp::resolver::results_type results8 =
+ resolver.resolve(ip::icmp::v4(), "", "", ec);
+ (void)results8;
+
+ ip::icmp::resolver::results_type results9 =
+ resolver.resolve(ip::icmp::v4(), "", "", ip::icmp::resolver::flags());
+ (void)results9;
+
+ ip::icmp::resolver::results_type results10 =
+ resolver.resolve(ip::icmp::v4(), "", "", ip::icmp::resolver::flags(), ec);
+ (void)results10;
+
+ ip::icmp::resolver::results_type results11 = resolver.resolve(e);
+ (void)results11;
+
+ ip::icmp::resolver::results_type results12 = resolver.resolve(e, ec);
+ (void)results12;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ resolver.async_resolve(q, resolve_handler());
+ int i1 = resolver.async_resolve(q, lazy);
+ (void)i1;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ resolver.async_resolve("", "", resolve_handler());
+ int i2 = resolver.async_resolve("", "", lazy);
+ (void)i2;
+
+ resolver.async_resolve("", "",
+ ip::icmp::resolver::flags(), resolve_handler());
+ int i3 = resolver.async_resolve("", "",
+ ip::icmp::resolver::flags(), lazy);
+ (void)i3;
+ resolver.async_resolve(ip::icmp::v4(), "", "", resolve_handler());
+ int i4 = resolver.async_resolve(ip::icmp::v4(), "", "", lazy);
+ (void)i4;
+
+ resolver.async_resolve(ip::icmp::v4(),
+ "", "", ip::icmp::resolver::flags(), resolve_handler());
+ int i5 = resolver.async_resolve(ip::icmp::v4(),
+ "", "", ip::icmp::resolver::flags(), lazy);
+ (void)i5;
+
+ resolver.async_resolve(e, resolve_handler());
+ int i6 = resolver.async_resolve(e, lazy);
+ (void)i6;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_icmp_resolver_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/icmp",
+ BOOST_ASIO_TEST_CASE(ip_icmp_socket_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_icmp_resolver_compile::test)
+)
diff --git a/src/boost/libs/asio/test/ip/multicast.cpp b/src/boost/libs/asio/test/ip/multicast.cpp
new file mode 100644
index 000000000..09b0a745e
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/multicast.cpp
@@ -0,0 +1,363 @@
+//
+// multicast.cpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/multicast.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// ip_multicast_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all nested classes, enums and constants in
+// ip::multicast compile and link correctly. Runtime failures are ignored.
+
+namespace ip_multicast_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ ip::udp::socket sock(ioc);
+ const ip::address address;
+ const ip::address_v4 address_v4;
+ const ip::address_v6 address_v6;
+
+ // join_group class.
+
+ ip::multicast::join_group join_group1;
+ ip::multicast::join_group join_group2(address);
+ ip::multicast::join_group join_group3(address_v4);
+ ip::multicast::join_group join_group4(address_v4, address_v4);
+ ip::multicast::join_group join_group5(address_v6);
+ ip::multicast::join_group join_group6(address_v6, 1);
+ sock.set_option(join_group6);
+
+ // leave_group class.
+
+ ip::multicast::leave_group leave_group1;
+ ip::multicast::leave_group leave_group2(address);
+ ip::multicast::leave_group leave_group3(address_v4);
+ ip::multicast::leave_group leave_group4(address_v4, address_v4);
+ ip::multicast::leave_group leave_group5(address_v6);
+ ip::multicast::leave_group leave_group6(address_v6, 1);
+ sock.set_option(leave_group6);
+
+ // outbound_interface class.
+
+ ip::multicast::outbound_interface outbound_interface1;
+ ip::multicast::outbound_interface outbound_interface2(address_v4);
+ ip::multicast::outbound_interface outbound_interface3(1);
+ sock.set_option(outbound_interface3);
+
+ // hops class.
+
+ ip::multicast::hops hops1(1024);
+ sock.set_option(hops1);
+ ip::multicast::hops hops2;
+ sock.get_option(hops2);
+ hops1 = 1;
+ (void)static_cast<int>(hops1.value());
+
+ // enable_loopback class.
+
+ ip::multicast::enable_loopback enable_loopback1(true);
+ sock.set_option(enable_loopback1);
+ ip::multicast::enable_loopback enable_loopback2;
+ sock.get_option(enable_loopback2);
+ enable_loopback1 = true;
+ (void)static_cast<bool>(enable_loopback1);
+ (void)static_cast<bool>(!enable_loopback1);
+ (void)static_cast<bool>(enable_loopback1.value());
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_multicast_compile
+
+//------------------------------------------------------------------------------
+
+// ip_multicast_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the socket options defined
+// in the ip::multicast namespace.
+
+namespace ip_multicast_runtime {
+
+#if defined(__hpux)
+// HP-UX doesn't declare this function extern "C", so it is declared again here
+// to avoid a linker error about an undefined symbol.
+extern "C" unsigned int if_nametoindex(const char*);
+#endif // defined(__hpux)
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ io_context ioc;
+ boost::system::error_code ec;
+
+ ip::udp::endpoint ep_v4(ip::address_v4::loopback(), 0);
+ ip::udp::socket sock_v4(ioc);
+ sock_v4.open(ep_v4.protocol(), ec);
+ sock_v4.bind(ep_v4, ec);
+ bool have_v4 = !ec;
+
+ ip::udp::endpoint ep_v6(ip::address_v6::loopback(), 0);
+ ip::udp::socket sock_v6(ioc);
+ sock_v6.open(ep_v6.protocol(), ec);
+ sock_v6.bind(ep_v6, ec);
+ bool have_v6 = !ec;
+
+ BOOST_ASIO_CHECK(have_v4 || have_v6);
+
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Windows CE seems to have problems with some multicast group addresses.
+ // The following address works on CE, but as it is not a private multicast
+ // address it will not be used on other platforms.
+ const ip::address multicast_address_v4 = ip::make_address("239.0.0.4", ec);
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ const ip::address multicast_address_v4 = ip::make_address("239.255.0.1", ec);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK(!have_v4 || !ec);
+
+#if (defined(__MACH__) && defined(__APPLE__)) \
+ || defined(__FreeBSD__) \
+ || defined(__NetBSD__) \
+ || defined(__OpenBSD__)
+ const ip::address multicast_address_v6 = ip::make_address("ff02::1%lo0", ec);
+#else // (defined(__MACH__) && defined(__APPLE__))
+ // || defined(__FreeBSD__)
+ // || defined(__NetBSD__)
+ // || defined(__OpenBSD__)
+ const ip::address multicast_address_v6 = ip::make_address("ff01::1", ec);
+#endif // (defined(__MACH__) && defined(__APPLE__))
+ // || defined(__FreeBSD__)
+ // || defined(__NetBSD__)
+ // || defined(__OpenBSD__)
+ BOOST_ASIO_CHECK(!have_v6 || !ec);
+
+ // join_group class.
+
+ if (have_v4)
+ {
+ ip::multicast::join_group join_group(multicast_address_v4);
+ sock_v4.set_option(join_group, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec || ec == error::no_such_device,
+ ec.value() << ", " << ec.message());
+
+ if (!ec)
+ {
+ // leave_group class.
+
+ ip::multicast::leave_group leave_group(multicast_address_v4);
+ sock_v4.set_option(leave_group, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ }
+ }
+
+ if (have_v6)
+ {
+ ip::multicast::join_group join_group(multicast_address_v6);
+ sock_v6.set_option(join_group, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec || ec == error::no_such_device,
+ ec.value() << ", " << ec.message());
+
+ if (!ec)
+ {
+ // leave_group class.
+
+ ip::multicast::leave_group leave_group(multicast_address_v6);
+ sock_v6.set_option(leave_group, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ }
+ }
+
+ // outbound_interface class.
+
+ if (have_v4)
+ {
+ ip::multicast::outbound_interface outbound_interface(
+ ip::address_v4::loopback());
+ sock_v4.set_option(outbound_interface, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ }
+
+ if (have_v6)
+ {
+#if defined(__hpux)
+ ip::multicast::outbound_interface outbound_interface(if_nametoindex("lo0"));
+#else
+ ip::multicast::outbound_interface outbound_interface(1);
+#endif
+ sock_v6.set_option(outbound_interface, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ }
+
+ // hops class.
+
+ if (have_v4)
+ {
+ ip::multicast::hops hops1(1);
+ BOOST_ASIO_CHECK(hops1.value() == 1);
+ sock_v4.set_option(hops1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ ip::multicast::hops hops2;
+ sock_v4.get_option(hops2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(hops2.value() == 1);
+
+ ip::multicast::hops hops3(0);
+ BOOST_ASIO_CHECK(hops3.value() == 0);
+ sock_v4.set_option(hops3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ ip::multicast::hops hops4;
+ sock_v4.get_option(hops4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(hops4.value() == 0);
+ }
+
+ if (have_v6)
+ {
+ ip::multicast::hops hops1(1);
+ BOOST_ASIO_CHECK(hops1.value() == 1);
+ sock_v6.set_option(hops1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ ip::multicast::hops hops2;
+ sock_v6.get_option(hops2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(hops2.value() == 1);
+
+ ip::multicast::hops hops3(0);
+ BOOST_ASIO_CHECK(hops3.value() == 0);
+ sock_v6.set_option(hops3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ ip::multicast::hops hops4;
+ sock_v6.get_option(hops4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(hops4.value() == 0);
+ }
+
+ // enable_loopback class.
+
+ if (have_v4)
+ {
+ ip::multicast::enable_loopback enable_loopback1(true);
+ BOOST_ASIO_CHECK(enable_loopback1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(enable_loopback1));
+ BOOST_ASIO_CHECK(!!enable_loopback1);
+ sock_v4.set_option(enable_loopback1, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ ip::multicast::enable_loopback enable_loopback2;
+ sock_v4.get_option(enable_loopback2, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Not supported under Windows CE but can get value.
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(enable_loopback2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(enable_loopback2));
+ BOOST_ASIO_CHECK(!!enable_loopback2);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ ip::multicast::enable_loopback enable_loopback3(false);
+ BOOST_ASIO_CHECK(!enable_loopback3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(enable_loopback3));
+ BOOST_ASIO_CHECK(!enable_loopback3);
+ sock_v4.set_option(enable_loopback3, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ ip::multicast::enable_loopback enable_loopback4;
+ sock_v4.get_option(enable_loopback4, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Not supported under Windows CE but can get value.
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(!enable_loopback4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(enable_loopback4));
+ BOOST_ASIO_CHECK(!enable_loopback4);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ }
+
+ if (have_v6)
+ {
+ ip::multicast::enable_loopback enable_loopback1(true);
+ BOOST_ASIO_CHECK(enable_loopback1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(enable_loopback1));
+ BOOST_ASIO_CHECK(!!enable_loopback1);
+ sock_v6.set_option(enable_loopback1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ ip::multicast::enable_loopback enable_loopback2;
+ sock_v6.get_option(enable_loopback2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(enable_loopback2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(enable_loopback2));
+ BOOST_ASIO_CHECK(!!enable_loopback2);
+
+ ip::multicast::enable_loopback enable_loopback3(false);
+ BOOST_ASIO_CHECK(!enable_loopback3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(enable_loopback3));
+ BOOST_ASIO_CHECK(!enable_loopback3);
+ sock_v6.set_option(enable_loopback3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ ip::multicast::enable_loopback enable_loopback4;
+ sock_v6.get_option(enable_loopback4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(!enable_loopback4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(enable_loopback4));
+ BOOST_ASIO_CHECK(!enable_loopback4);
+ }
+}
+
+} // namespace ip_multicast_runtime
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/multicast",
+ BOOST_ASIO_TEST_CASE(ip_multicast_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_multicast_runtime::test)
+)
diff --git a/src/boost/libs/asio/test/ip/network_v4.cpp b/src/boost/libs/asio/test/ip/network_v4.cpp
new file mode 100644
index 000000000..59d10dc31
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/network_v4.cpp
@@ -0,0 +1,314 @@
+//
+// network_v4.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/network_v4.hpp>
+
+#include "../unit_test.hpp"
+#include <sstream>
+
+//------------------------------------------------------------------------------
+
+// ip_network_v4_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::network_v4 compile and link correctly. Runtime failures are ignored.
+
+namespace ip_network_v4_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ boost::system::error_code ec;
+
+ // network_v4 constructors.
+
+ ip::network_v4 net1(ip::make_address_v4("192.168.1.0"), 32);
+ ip::network_v4 net2(ip::make_address_v4("192.168.1.0"),
+ ip::make_address_v4("255.255.255.0"));
+
+ // network_v4 functions.
+
+ ip::address_v4 addr1 = net1.address();
+ (void)addr1;
+
+ unsigned short prefix_len = net1.prefix_length();
+ (void)prefix_len;
+
+ ip::address_v4 addr2 = net1.netmask();
+ (void)addr2;
+
+ ip::address_v4 addr3 = net1.network();
+ (void)addr3;
+
+ ip::address_v4 addr4 = net1.broadcast();
+ (void)addr4;
+
+ ip::address_v4_range hosts = net1.hosts();
+ (void)hosts;
+
+ ip::network_v4 net3 = net1.canonical();
+ (void)net3;
+
+ bool b1 = net1.is_host();
+ (void)b1;
+
+ bool b2 = net1.is_subnet_of(net2);
+ (void)b2;
+
+ std::string s1 = net1.to_string();
+ (void)s1;
+
+ std::string s2 = net1.to_string(ec);
+ (void)s2;
+
+ // network_v4 comparisons.
+
+ bool b3 = (net1 == net2);
+ (void)b3;
+
+ bool b4 = (net1 != net2);
+ (void)b4;
+
+ // network_v4 creation functions.
+
+ net1 = ip::make_network_v4(ip::address_v4(), 24);
+ net1 = ip::make_network_v4(ip::address_v4(), ip::address_v4());
+ net1 = ip::make_network_v4("10.0.0.0/8");
+ net1 = ip::make_network_v4("10.0.0.0/8", ec);
+ net1 = ip::make_network_v4(s1);
+ net1 = ip::make_network_v4(s1, ec);
+#if defined(BOOST_ASIO_HAS_STRING_VIEW)
+# if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ std::string_view string_view_value("10.0.0.0/8");
+# elif defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ std::experimental::string_view string_view_value("10.0.0.0/8");
+# endif // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ net1 = ip::make_network_v4(string_view_value);
+ net1 = ip::make_network_v4(string_view_value, ec);
+#endif // defined(BOOST_ASIO_HAS_STRING_VIEW)
+
+ // network_v4 I/O.
+
+ std::ostringstream os;
+ os << net1;
+
+#if !defined(BOOST_NO_STD_WSTREAMBUF)
+ std::wostringstream wos;
+ wos << net1;
+#endif // !defined(BOOST_NO_STD_WSTREAMBUF)
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_network_v4_compile
+
+//------------------------------------------------------------------------------
+
+// ip_network_v4_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that the various public member functions meet the
+// necessary postconditions.
+
+namespace ip_network_v4_runtime {
+
+void test()
+{
+ using boost::asio::ip::address_v4;
+ using boost::asio::ip::make_address_v4;
+ using boost::asio::ip::network_v4;
+ using boost::asio::ip::make_network_v4;
+
+ address_v4 addr = make_address_v4("1.2.3.4");
+
+ // calculate prefix length
+
+ network_v4 net1(addr, make_address_v4("255.255.255.0"));
+ BOOST_ASIO_CHECK(net1.prefix_length() == 24);
+
+ network_v4 net2(addr, make_address_v4("255.255.255.192"));
+ BOOST_ASIO_CHECK(net2.prefix_length() == 26);
+
+ network_v4 net3(addr, make_address_v4("128.0.0.0"));
+ BOOST_ASIO_CHECK(net3.prefix_length() == 1);
+
+ std::string msg;
+ try
+ {
+ make_network_v4(addr, make_address_v4("255.255.255.1"));
+ }
+ catch(std::exception& ex)
+ {
+ msg = ex.what();
+ }
+ BOOST_ASIO_CHECK(msg == std::string("non-contiguous netmask"));
+
+ msg.clear();
+ try
+ {
+ make_network_v4(addr, make_address_v4("0.255.255.0"));
+ }
+ catch(std::exception& ex)
+ {
+ msg = ex.what();
+ }
+ BOOST_ASIO_CHECK(msg == std::string("non-contiguous netmask"));
+
+ // calculate netmask
+
+ network_v4 net4(addr, 23);
+ BOOST_ASIO_CHECK(net4.netmask() == make_address_v4("255.255.254.0"));
+
+ network_v4 net5(addr, 12);
+ BOOST_ASIO_CHECK(net5.netmask() == make_address_v4("255.240.0.0"));
+
+ network_v4 net6(addr, 24);
+ BOOST_ASIO_CHECK(net6.netmask() == make_address_v4("255.255.255.0"));
+
+ network_v4 net7(addr, 16);
+ BOOST_ASIO_CHECK(net7.netmask() == make_address_v4("255.255.0.0"));
+
+ network_v4 net8(addr, 8);
+ BOOST_ASIO_CHECK(net8.netmask() == make_address_v4("255.0.0.0"));
+
+ network_v4 net9(addr, 32);
+ BOOST_ASIO_CHECK(net9.netmask() == make_address_v4("255.255.255.255"));
+
+ network_v4 net10(addr, 1);
+ BOOST_ASIO_CHECK(net10.netmask() == make_address_v4("128.0.0.0"));
+
+ network_v4 net11(addr, 0);
+ BOOST_ASIO_CHECK(net11.netmask() == make_address_v4("0.0.0.0"));
+
+ msg.clear();
+ try
+ {
+ make_network_v4(addr, 33);
+ }
+ catch(std::out_of_range& ex)
+ {
+ msg = ex.what();
+ }
+ BOOST_ASIO_CHECK(msg == std::string("prefix length too large"));
+
+ // construct address range from address and prefix length
+ BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.100"), 32).network() == make_address_v4("192.168.77.100"));
+ BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.100"), 24).network() == make_address_v4("192.168.77.0"));
+ BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.128"), 25).network() == make_address_v4("192.168.77.128"));
+
+ // construct address range from string in CIDR notation
+ BOOST_ASIO_CHECK(make_network_v4("192.168.77.100/32").network() == make_address_v4("192.168.77.100"));
+ BOOST_ASIO_CHECK(make_network_v4("192.168.77.100/24").network() == make_address_v4("192.168.77.0"));
+ BOOST_ASIO_CHECK(make_network_v4("192.168.77.128/25").network() == make_address_v4("192.168.77.128"));
+
+ // construct network from invalid string
+ boost::system::error_code ec;
+ make_network_v4("10.0.0.256/24", ec);
+ BOOST_ASIO_CHECK(!!ec);
+ make_network_v4("10.0.0.0/33", ec);
+ BOOST_ASIO_CHECK(!!ec);
+ make_network_v4("10.0.0.0/-1", ec);
+ BOOST_ASIO_CHECK(!!ec);
+ make_network_v4("10.0.0.0/", ec);
+ BOOST_ASIO_CHECK(!!ec);
+ make_network_v4("10.0.0.0", ec);
+ BOOST_ASIO_CHECK(!!ec);
+
+ // prefix length
+ BOOST_ASIO_CHECK(make_network_v4("193.99.144.80/24").prefix_length() == 24);
+ BOOST_ASIO_CHECK(network_v4(make_address_v4("193.99.144.80"), 24).prefix_length() == 24);
+ BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.0"), make_address_v4("255.255.255.0")).prefix_length() == 24);
+
+ // to string
+ std::string a("192.168.77.0/32");
+ BOOST_ASIO_CHECK(make_network_v4(a.c_str()).to_string() == a);
+ BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.10"), 24).to_string() == std::string("192.168.77.10/24"));
+
+ // return host part
+ BOOST_ASIO_CHECK(make_network_v4("192.168.77.11/24").address() == make_address_v4("192.168.77.11"));
+
+ // return host in CIDR notation
+ BOOST_ASIO_CHECK(make_network_v4("192.168.78.30/20").address().to_string() == "192.168.78.30");
+
+ // return network in CIDR notation
+ BOOST_ASIO_CHECK(make_network_v4("192.168.78.30/20").canonical().to_string() == "192.168.64.0/20");
+
+ // is host
+ BOOST_ASIO_CHECK(make_network_v4("192.168.77.0/32").is_host());
+ BOOST_ASIO_CHECK(!make_network_v4("192.168.77.0/31").is_host());
+
+ // is real subnet of
+ BOOST_ASIO_CHECK(make_network_v4("192.168.0.192/24").is_subnet_of(make_network_v4("192.168.0.0/16")));
+ BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.192.168/16")));
+ BOOST_ASIO_CHECK(make_network_v4("192.168.0.192/24").is_subnet_of(make_network_v4("192.168.192.168/16")));
+ BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.0.0/16")));
+ BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.0.0/23")));
+ BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.0.0/0")));
+ BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/32").is_subnet_of(make_network_v4("192.168.0.0/24")));
+
+ BOOST_ASIO_CHECK(!make_network_v4("192.168.0.0/32").is_subnet_of(make_network_v4("192.168.0.0/32")));
+ BOOST_ASIO_CHECK(!make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.1.0/24")));
+ BOOST_ASIO_CHECK(!make_network_v4("192.168.0.0/16").is_subnet_of(make_network_v4("192.168.1.0/24")));
+
+ network_v4 r(make_network_v4("192.168.0.0/24"));
+ BOOST_ASIO_CHECK(!r.is_subnet_of(r));
+
+ network_v4 net12(make_network_v4("192.168.0.2/24"));
+ network_v4 net13(make_network_v4("192.168.1.1/28"));
+ network_v4 net14(make_network_v4("192.168.1.21/28"));
+ // network
+ BOOST_ASIO_CHECK(net12.network() == make_address_v4("192.168.0.0"));
+ BOOST_ASIO_CHECK(net13.network() == make_address_v4("192.168.1.0"));
+ BOOST_ASIO_CHECK(net14.network() == make_address_v4("192.168.1.16"));
+ // netmask
+ BOOST_ASIO_CHECK(net12.netmask() == make_address_v4("255.255.255.0"));
+ BOOST_ASIO_CHECK(net13.netmask() == make_address_v4("255.255.255.240"));
+ BOOST_ASIO_CHECK(net14.netmask() == make_address_v4("255.255.255.240"));
+ // broadcast
+ BOOST_ASIO_CHECK(net12.broadcast() == make_address_v4("192.168.0.255"));
+ BOOST_ASIO_CHECK(net13.broadcast() == make_address_v4("192.168.1.15"));
+ BOOST_ASIO_CHECK(net14.broadcast() == make_address_v4("192.168.1.31"));
+ // iterator
+ BOOST_ASIO_CHECK(std::distance(net12.hosts().begin(),net12.hosts().end()) == 254);
+ BOOST_ASIO_CHECK(*net12.hosts().begin() == make_address_v4("192.168.0.1"));
+ BOOST_ASIO_CHECK(net12.hosts().end() != net12.hosts().find(make_address_v4("192.168.0.10")));
+ BOOST_ASIO_CHECK(net12.hosts().end() == net12.hosts().find(make_address_v4("192.168.1.10")));
+ BOOST_ASIO_CHECK(std::distance(net13.hosts().begin(),net13.hosts().end()) == 14);
+ BOOST_ASIO_CHECK(*net13.hosts().begin() == make_address_v4("192.168.1.1"));
+ BOOST_ASIO_CHECK(net13.hosts().end() != net13.hosts().find(make_address_v4("192.168.1.14")));
+ BOOST_ASIO_CHECK(net13.hosts().end() == net13.hosts().find(make_address_v4("192.168.1.15")));
+ BOOST_ASIO_CHECK(std::distance(net14.hosts().begin(),net14.hosts().end()) == 14);
+ BOOST_ASIO_CHECK(*net14.hosts().begin() == make_address_v4("192.168.1.17"));
+ BOOST_ASIO_CHECK(net14.hosts().end() != net14.hosts().find(make_address_v4("192.168.1.30")));
+ BOOST_ASIO_CHECK(net14.hosts().end() == net14.hosts().find(make_address_v4("192.168.1.31")));
+}
+
+} // namespace ip_network_v4_runtime
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/network_v4",
+ BOOST_ASIO_TEST_CASE(ip_network_v4_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_network_v4_runtime::test)
+)
diff --git a/src/boost/libs/asio/test/ip/network_v6.cpp b/src/boost/libs/asio/test/ip/network_v6.cpp
new file mode 100644
index 000000000..cfe97ce61
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/network_v6.cpp
@@ -0,0 +1,238 @@
+//
+// network_v6.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/network_v6.hpp>
+
+#include "../unit_test.hpp"
+#include <sstream>
+
+//------------------------------------------------------------------------------
+
+// ip_network_v6_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::network_v6 compile and link correctly. Runtime failures are ignored.
+
+namespace ip_network_v6_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ boost::system::error_code ec;
+
+ // network_v6 constructors.
+
+ ip::network_v6 net1(ip::make_address_v6("2001:370::10:7344"), 64);
+ ip::network_v6 net2(ip::make_address_v6("2001:370::10:7345"), 96);
+
+ // network_v6 functions.
+
+ ip::address_v6 addr1 = net1.address();
+ (void)addr1;
+
+ unsigned short prefix_len = net1.prefix_length();
+ (void)prefix_len;
+
+ ip::address_v6 addr3 = net1.network();
+ (void)addr3;
+
+ ip::address_v6_range hosts = net1.hosts();
+ (void)hosts;
+
+ ip::network_v6 net3 = net1.canonical();
+ (void)net3;
+
+ bool b1 = net1.is_host();
+ (void)b1;
+
+ bool b2 = net1.is_subnet_of(net2);
+ (void)b2;
+
+ std::string s1 = net1.to_string();
+ (void)s1;
+
+ std::string s2 = net1.to_string(ec);
+ (void)s2;
+
+ // network_v6 comparisons.
+
+ bool b3 = (net1 == net2);
+ (void)b3;
+
+ bool b4 = (net1 != net2);
+ (void)b4;
+
+ // network_v6 creation functions.
+
+ net1 = ip::make_network_v6(ip::address_v6(), 24);
+ net1 = ip::make_network_v6("10.0.0.0/8");
+ net1 = ip::make_network_v6("10.0.0.0/8", ec);
+ net1 = ip::make_network_v6(s1);
+ net1 = ip::make_network_v6(s1, ec);
+#if defined(BOOST_ASIO_HAS_STRING_VIEW)
+# if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ std::string_view string_view_value("0::0/8");
+# elif defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ std::experimental::string_view string_view_value("0::0/8");
+# endif // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+ net1 = ip::make_network_v6(string_view_value);
+ net1 = ip::make_network_v6(string_view_value, ec);
+#endif // defined(BOOST_ASIO_STD_STRING_VIEW)
+
+ // network_v6 I/O.
+
+ std::ostringstream os;
+ os << net1;
+
+#if !defined(BOOST_NO_STD_WSTREAMBUF)
+ std::wostringstream wos;
+ wos << net1;
+#endif // !defined(BOOST_NO_STD_WSTREAMBUF)
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_network_v6_compile
+
+//------------------------------------------------------------------------------
+
+// ip_network_v6_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that the various public member functions meet the
+// necessary postconditions.
+
+namespace ip_network_v6_runtime {
+
+void test()
+{
+ using boost::asio::ip::address_v6;
+ using boost::asio::ip::make_address_v6;
+ using boost::asio::ip::network_v6;
+ using boost::asio::ip::make_network_v6;
+
+ address_v6 addr = make_address_v6("2001:370::10:7344");
+
+ std::string msg;
+ try
+ {
+ make_network_v6(addr, 129);
+ }
+ catch(std::out_of_range& ex)
+ {
+ msg = ex.what();
+ }
+ BOOST_ASIO_CHECK(msg == std::string("prefix length too large"));
+
+ // construct address range from address and prefix length
+ BOOST_ASIO_CHECK(network_v6(make_address_v6("2001:370::10:7344"), 128).network() == make_address_v6("2001:370::10:7344"));
+ BOOST_ASIO_CHECK(network_v6(make_address_v6("2001:370::10:7344"), 64).network() == make_address_v6("2001:370::"));
+ BOOST_ASIO_CHECK(network_v6(make_address_v6("2001:370::10:7344"), 27).network() == make_address_v6("2001:360::"));
+
+ // construct address range from string in CIDR notation
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:7344/128").network() == make_address_v6("2001:370::10:7344"));
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:7344/64").network() == make_address_v6("2001:370::"));
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:7344/27").network() == make_address_v6("2001:360::"));
+
+ // construct network from invalid string
+ boost::system::error_code ec;
+ make_network_v6("a:b/24", ec);
+ BOOST_ASIO_CHECK(!!ec);
+ make_network_v6("2001:370::10:7344/129", ec);
+ BOOST_ASIO_CHECK(!!ec);
+ make_network_v6("2001:370::10:7344/-1", ec);
+ BOOST_ASIO_CHECK(!!ec);
+ make_network_v6("2001:370::10:7344/", ec);
+ BOOST_ASIO_CHECK(!!ec);
+ make_network_v6("2001:370::10:7344", ec);
+ BOOST_ASIO_CHECK(!!ec);
+
+ // prefix length
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:7344/128").prefix_length() == 128);
+ BOOST_ASIO_CHECK(network_v6(make_address_v6("2001:370::10:7344"), 27).prefix_length() == 27);
+
+ // to string
+ std::string a("2001:370::10:7344/64");
+ BOOST_ASIO_CHECK(make_network_v6(a.c_str()).to_string() == a);
+ BOOST_ASIO_CHECK(network_v6(make_address_v6("2001:370::10:7344"), 27).to_string() == std::string("2001:370::10:7344/27"));
+
+ // return host part
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:7344/64").address() == make_address_v6("2001:370::10:7344"));
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:7344/27").address().to_string() == "2001:370::10:7344");
+
+ // return network in CIDR notation
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:7344/27").canonical().to_string() == "2001:360::/27");
+
+ // is host
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:7344/128").is_host());
+ BOOST_ASIO_CHECK(!make_network_v6("2001:370::10:7344/127").is_host());
+
+ // is real subnet of
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::10:3744/64").is_subnet_of(make_network_v6("2001:370::/16")));
+ BOOST_ASIO_CHECK(make_network_v6("2001:370::/64").is_subnet_of(make_network_v6("2001:370::/16")));
+ BOOST_ASIO_CHECK(make_network_v6("2001:0db8:85a3::/64").is_subnet_of(make_network_v6("2001:0d00::/24")));
+
+ BOOST_ASIO_CHECK(!make_network_v6("2001:370::10:3744/128").is_subnet_of(make_network_v6("2001:370::10:3744/128")));
+ BOOST_ASIO_CHECK(make_network_v6("2001:0db8:85a3::/64").is_subnet_of(make_network_v6("2001:0dc0::/24")));
+
+ network_v6 r(make_network_v6("2001:370::/64"));
+ BOOST_ASIO_CHECK(!r.is_subnet_of(r));
+
+ network_v6 net12(make_network_v6("2001:370::10:7344/64"));
+ network_v6 net13(make_network_v6("2001:0db8::/127"));
+ network_v6 net14(make_network_v6("2001:0db8::/125"));
+ network_v6 net15(make_network_v6("2001:0db8::/119"));
+
+ // network
+ BOOST_ASIO_CHECK(net12.network() == make_address_v6("2001:370::"));
+ BOOST_ASIO_CHECK(net13.network() == make_address_v6("2001:0db8::"));
+ BOOST_ASIO_CHECK(net14.network() == make_address_v6("2001:0db8::"));
+ BOOST_ASIO_CHECK(net15.network() == make_address_v6("2001:0db8::"));
+
+ // iterator
+ //BOOST_ASIO_CHECK(std::distance(net12.hosts().begin(),net12.hosts().end()) == 18446744073709552000);
+ BOOST_ASIO_CHECK(std::distance(net13.hosts().begin(),net13.hosts().end()) == 2);
+ BOOST_ASIO_CHECK(std::distance(net14.hosts().begin(),net14.hosts().end()) == 8);
+ BOOST_ASIO_CHECK(std::distance(net15.hosts().begin(),net15.hosts().end()) == 512);
+ BOOST_ASIO_CHECK(*net12.hosts().begin() == make_address_v6("2001:0370::"));
+ BOOST_ASIO_CHECK(net12.hosts().end() != net12.hosts().find(make_address_v6("2001:0370::ffff:ffff:ffff:ffff")));
+ BOOST_ASIO_CHECK(*net13.hosts().begin() == make_address_v6("2001:0db8::"));
+ BOOST_ASIO_CHECK(net13.hosts().end() != net13.hosts().find(make_address_v6("2001:0db8::1")));
+ BOOST_ASIO_CHECK(net13.hosts().end() == net13.hosts().find(make_address_v6("2001:0db8::2")));
+ BOOST_ASIO_CHECK(*net14.hosts().begin() == make_address_v6("2001:0db8::"));
+ BOOST_ASIO_CHECK(net14.hosts().end() != net14.hosts().find(make_address_v6("2001:0db8::7")));
+ BOOST_ASIO_CHECK(net14.hosts().end() == net14.hosts().find(make_address_v6("2001:0db8::8")));
+ BOOST_ASIO_CHECK(*net15.hosts().begin() == make_address_v6("2001:0db8::"));
+ BOOST_ASIO_CHECK(net15.hosts().end() != net15.hosts().find(make_address_v6("2001:0db8::01ff")));
+ BOOST_ASIO_CHECK(net15.hosts().end() == net15.hosts().find(make_address_v6("2001:0db8::0200")));
+}
+
+} // namespace ip_network_v6_runtime
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/network_v6",
+ BOOST_ASIO_TEST_CASE(ip_network_v6_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_network_v6_runtime::test)
+)
diff --git a/src/boost/libs/asio/test/ip/resolver_query_base.cpp b/src/boost/libs/asio/test/ip/resolver_query_base.cpp
new file mode 100644
index 000000000..d955a96ae
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/resolver_query_base.cpp
@@ -0,0 +1,25 @@
+//
+// resolver_query_base.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/resolver_query_base.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/resolver_query_base",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ip/tcp.cpp b/src/boost/libs/asio/test/ip/tcp.cpp
new file mode 100644
index 000000000..fc204ea5d
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/tcp.cpp
@@ -0,0 +1,1346 @@
+//
+// tcp.cpp
+// ~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Enable cancel() support on Windows.
+#define BOOST_ASIO_ENABLE_CANCELIO 1
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/tcp.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/write.hpp>
+#include "../unit_test.hpp"
+#include "../archetypes/async_result.hpp"
+#include "../archetypes/gettable_socket_option.hpp"
+#include "../archetypes/io_control_command.hpp"
+#include "../archetypes/settable_socket_option.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <boost/array.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_compile test
+// ~~~~~~~~~~~~~~~~~~~
+// The following test checks that all nested classes, enums and constants in
+// ip::tcp compile and link correctly. Runtime failures are ignored.
+
+namespace ip_tcp_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ ip::tcp::socket sock(ioc);
+
+ // no_delay class.
+
+ ip::tcp::no_delay no_delay1(true);
+ sock.set_option(no_delay1);
+ ip::tcp::no_delay no_delay2;
+ sock.get_option(no_delay2);
+ no_delay1 = true;
+ (void)static_cast<bool>(no_delay1);
+ (void)static_cast<bool>(!no_delay1);
+ (void)static_cast<bool>(no_delay1.value());
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_tcp_compile
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_runtime test
+// ~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the ip::tcp class.
+
+namespace ip_tcp_runtime {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ io_context ioc;
+ ip::tcp::socket sock(ioc, ip::tcp::v4());
+ boost::system::error_code ec;
+
+ // no_delay class.
+
+ ip::tcp::no_delay no_delay1(true);
+ BOOST_ASIO_CHECK(no_delay1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(no_delay1));
+ BOOST_ASIO_CHECK(!!no_delay1);
+ sock.set_option(no_delay1, ec);
+ BOOST_ASIO_CHECK(!ec);
+
+ ip::tcp::no_delay no_delay2;
+ sock.get_option(no_delay2, ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(no_delay2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(no_delay2));
+ BOOST_ASIO_CHECK(!!no_delay2);
+
+ ip::tcp::no_delay no_delay3(false);
+ BOOST_ASIO_CHECK(!no_delay3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(no_delay3));
+ BOOST_ASIO_CHECK(!no_delay3);
+ sock.set_option(no_delay3, ec);
+ BOOST_ASIO_CHECK(!ec);
+
+ ip::tcp::no_delay no_delay4;
+ sock.get_option(no_delay4, ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(!no_delay4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(no_delay4));
+ BOOST_ASIO_CHECK(!no_delay4);
+}
+
+} // namespace ip_tcp_runtime
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::tcp::socket compile and link correctly. Runtime failures are ignored.
+
+namespace ip_tcp_socket_compile {
+
+struct connect_handler
+{
+ connect_handler() {}
+ void operator()(const boost::system::error_code&) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ connect_handler(connect_handler&&) {}
+private:
+ connect_handler(const connect_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct wait_handler
+{
+ wait_handler() {}
+ void operator()(const boost::system::error_code&) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ wait_handler(wait_handler&&) {}
+private:
+ wait_handler(const wait_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct send_handler
+{
+ send_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ send_handler(send_handler&&) {}
+private:
+ send_handler(const send_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct receive_handler
+{
+ receive_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ receive_handler(receive_handler&&) {}
+private:
+ receive_handler(const receive_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct write_some_handler
+{
+ write_some_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ write_some_handler(write_some_handler&&) {}
+private:
+ write_some_handler(const write_some_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct read_some_handler
+{
+ read_some_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ read_some_handler(read_some_handler&&) {}
+private:
+ read_some_handler(const read_some_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ using boost::array;
+#else // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ using std::array;
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ array<boost::asio::mutable_buffer, 2> mutable_buffers = {{
+ boost::asio::buffer(mutable_char_buffer, 10),
+ boost::asio::buffer(mutable_char_buffer + 10, 10) }};
+ array<boost::asio::const_buffer, 2> const_buffers = {{
+ boost::asio::buffer(const_char_buffer, 10),
+ boost::asio::buffer(const_char_buffer + 10, 10) }};
+ socket_base::message_flags in_flags = 0;
+ archetypes::settable_socket_option<void> settable_socket_option1;
+ archetypes::settable_socket_option<int> settable_socket_option2;
+ archetypes::settable_socket_option<double> settable_socket_option3;
+ archetypes::gettable_socket_option<void> gettable_socket_option1;
+ archetypes::gettable_socket_option<int> gettable_socket_option2;
+ archetypes::gettable_socket_option<double> gettable_socket_option3;
+ archetypes::io_control_command io_control_command;
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_stream_socket constructors.
+
+ ip::tcp::socket socket1(ioc);
+ ip::tcp::socket socket2(ioc, ip::tcp::v4());
+ ip::tcp::socket socket3(ioc, ip::tcp::v6());
+ ip::tcp::socket socket4(ioc, ip::tcp::endpoint(ip::tcp::v4(), 0));
+ ip::tcp::socket socket5(ioc, ip::tcp::endpoint(ip::tcp::v6(), 0));
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::tcp::socket::native_handle_type native_socket1
+ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ip::tcp::socket socket6(ioc, ip::tcp::v4(), native_socket1);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ ip::tcp::socket socket7(ioc_ex);
+ ip::tcp::socket socket8(ioc_ex, ip::tcp::v4());
+ ip::tcp::socket socket9(ioc_ex, ip::tcp::v6());
+ ip::tcp::socket socket10(ioc_ex, ip::tcp::endpoint(ip::tcp::v4(), 0));
+ ip::tcp::socket socket11(ioc_ex, ip::tcp::endpoint(ip::tcp::v6(), 0));
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::tcp::socket::native_handle_type native_socket2
+ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ip::tcp::socket socket12(ioc_ex, ip::tcp::v4(), native_socket2);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ ip::tcp::socket socket13(std::move(socket5));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_stream_socket operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ socket1 = ip::tcp::socket(ioc);
+ socket1 = std::move(socket2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ ip::tcp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ ip::tcp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ const ip::tcp::socket& socket14 = socket1;
+ const ip::tcp::socket::lowest_layer_type& lowest_layer2
+ = socket14.lowest_layer();
+ (void)lowest_layer2;
+
+ socket1.open(ip::tcp::v4());
+ socket1.open(ip::tcp::v6());
+ socket1.open(ip::tcp::v4(), ec);
+ socket1.open(ip::tcp::v6(), ec);
+
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::tcp::socket::native_handle_type native_socket3
+ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ socket1.assign(ip::tcp::v4(), native_socket3);
+ ip::tcp::socket::native_handle_type native_socket4
+ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ socket1.assign(ip::tcp::v4(), native_socket4, ec);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ socket1.release();
+ socket1.release(ec);
+
+ ip::tcp::socket::native_handle_type native_socket5
+ = socket1.native_handle();
+ (void)native_socket5;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(ip::tcp::endpoint(ip::tcp::v4(), 0));
+ socket1.bind(ip::tcp::endpoint(ip::tcp::v6(), 0));
+ socket1.bind(ip::tcp::endpoint(ip::tcp::v4(), 0), ec);
+ socket1.bind(ip::tcp::endpoint(ip::tcp::v6(), 0), ec);
+
+ socket1.connect(ip::tcp::endpoint(ip::tcp::v4(), 0));
+ socket1.connect(ip::tcp::endpoint(ip::tcp::v6(), 0));
+ socket1.connect(ip::tcp::endpoint(ip::tcp::v4(), 0), ec);
+ socket1.connect(ip::tcp::endpoint(ip::tcp::v6(), 0), ec);
+
+ socket1.async_connect(ip::tcp::endpoint(ip::tcp::v4(), 0),
+ connect_handler());
+ socket1.async_connect(ip::tcp::endpoint(ip::tcp::v6(), 0),
+ connect_handler());
+ int i1 = socket1.async_connect(ip::tcp::endpoint(ip::tcp::v4(), 0), lazy);
+ (void)i1;
+ int i2 = socket1.async_connect(ip::tcp::endpoint(ip::tcp::v6(), 0), lazy);
+ (void)i2;
+
+ socket1.set_option(settable_socket_option1);
+ socket1.set_option(settable_socket_option1, ec);
+ socket1.set_option(settable_socket_option2);
+ socket1.set_option(settable_socket_option2, ec);
+ socket1.set_option(settable_socket_option3);
+ socket1.set_option(settable_socket_option3, ec);
+
+ socket1.get_option(gettable_socket_option1);
+ socket1.get_option(gettable_socket_option1, ec);
+ socket1.get_option(gettable_socket_option2);
+ socket1.get_option(gettable_socket_option2, ec);
+ socket1.get_option(gettable_socket_option3);
+ socket1.get_option(gettable_socket_option3, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ bool non_blocking1 = socket1.non_blocking();
+ (void)non_blocking1;
+ socket1.non_blocking(true);
+ socket1.non_blocking(false, ec);
+
+ bool non_blocking2 = socket1.native_non_blocking();
+ (void)non_blocking2;
+ socket1.native_non_blocking(true);
+ socket1.native_non_blocking(false, ec);
+
+ ip::tcp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ ip::tcp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ ip::tcp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ ip::tcp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ socket1.wait(socket_base::wait_read);
+ socket1.wait(socket_base::wait_write, ec);
+
+ socket1.async_wait(socket_base::wait_read, wait_handler());
+ int i3 = socket1.async_wait(socket_base::wait_write, lazy);
+ (void)i3;
+
+ // basic_stream_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer));
+ socket1.send(buffer(const_char_buffer));
+ socket1.send(mutable_buffers);
+ socket1.send(const_buffers);
+ socket1.send(null_buffers());
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(mutable_buffers, in_flags);
+ socket1.send(const_buffers, in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(mutable_buffers, in_flags, ec);
+ socket1.send(const_buffers, in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), send_handler());
+ socket1.async_send(buffer(const_char_buffer), send_handler());
+ socket1.async_send(mutable_buffers, send_handler());
+ socket1.async_send(const_buffers, send_handler());
+ socket1.async_send(null_buffers(), send_handler());
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler());
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler());
+ socket1.async_send(mutable_buffers, in_flags, send_handler());
+ socket1.async_send(const_buffers, in_flags, send_handler());
+ socket1.async_send(null_buffers(), in_flags, send_handler());
+ int i4 = socket1.async_send(buffer(mutable_char_buffer), lazy);
+ (void)i4;
+ int i5 = socket1.async_send(buffer(const_char_buffer), lazy);
+ (void)i5;
+ int i6 = socket1.async_send(mutable_buffers, lazy);
+ (void)i6;
+ int i7 = socket1.async_send(const_buffers, lazy);
+ (void)i7;
+ int i8 = socket1.async_send(null_buffers(), lazy);
+ (void)i8;
+ int i9 = socket1.async_send(buffer(mutable_char_buffer), in_flags, lazy);
+ (void)i9;
+ int i10 = socket1.async_send(buffer(const_char_buffer), in_flags, lazy);
+ (void)i10;
+ int i11 = socket1.async_send(mutable_buffers, in_flags, lazy);
+ (void)i11;
+ int i12 = socket1.async_send(const_buffers, in_flags, lazy);
+ (void)i12;
+ int i13 = socket1.async_send(null_buffers(), in_flags, lazy);
+ (void)i13;
+
+ socket1.receive(buffer(mutable_char_buffer));
+ socket1.receive(mutable_buffers);
+ socket1.receive(null_buffers());
+ socket1.receive(buffer(mutable_char_buffer), in_flags);
+ socket1.receive(mutable_buffers, in_flags);
+ socket1.receive(null_buffers(), in_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.receive(mutable_buffers, in_flags, ec);
+ socket1.receive(null_buffers(), in_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), receive_handler());
+ socket1.async_receive(mutable_buffers, receive_handler());
+ socket1.async_receive(null_buffers(), receive_handler());
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ receive_handler());
+ socket1.async_receive(mutable_buffers, in_flags, receive_handler());
+ socket1.async_receive(null_buffers(), in_flags, receive_handler());
+ int i14 = socket1.async_receive(buffer(mutable_char_buffer), lazy);
+ (void)i14;
+ int i15 = socket1.async_receive(mutable_buffers, lazy);
+ (void)i15;
+ int i16 = socket1.async_receive(null_buffers(), lazy);
+ (void)i16;
+ int i17 = socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ lazy);
+ (void)i17;
+ int i18 = socket1.async_receive(mutable_buffers, in_flags, lazy);
+ (void)i18;
+ int i19 = socket1.async_receive(null_buffers(), in_flags, lazy);
+ (void)i19;
+
+ socket1.write_some(buffer(mutable_char_buffer));
+ socket1.write_some(buffer(const_char_buffer));
+ socket1.write_some(mutable_buffers);
+ socket1.write_some(const_buffers);
+ socket1.write_some(null_buffers());
+ socket1.write_some(buffer(mutable_char_buffer), ec);
+ socket1.write_some(buffer(const_char_buffer), ec);
+ socket1.write_some(mutable_buffers, ec);
+ socket1.write_some(const_buffers, ec);
+ socket1.write_some(null_buffers(), ec);
+
+ socket1.async_write_some(buffer(mutable_char_buffer), write_some_handler());
+ socket1.async_write_some(buffer(const_char_buffer), write_some_handler());
+ socket1.async_write_some(mutable_buffers, write_some_handler());
+ socket1.async_write_some(const_buffers, write_some_handler());
+ socket1.async_write_some(null_buffers(), write_some_handler());
+ int i20 = socket1.async_write_some(buffer(mutable_char_buffer), lazy);
+ (void)i20;
+ int i21 = socket1.async_write_some(buffer(const_char_buffer), lazy);
+ (void)i21;
+ int i22 = socket1.async_write_some(mutable_buffers, lazy);
+ (void)i22;
+ int i23 = socket1.async_write_some(const_buffers, lazy);
+ (void)i23;
+ int i24 = socket1.async_write_some(null_buffers(), lazy);
+ (void)i24;
+
+ socket1.read_some(buffer(mutable_char_buffer));
+ socket1.read_some(mutable_buffers);
+ socket1.read_some(null_buffers());
+ socket1.read_some(buffer(mutable_char_buffer), ec);
+ socket1.read_some(mutable_buffers, ec);
+ socket1.read_some(null_buffers(), ec);
+
+ socket1.async_read_some(buffer(mutable_char_buffer), read_some_handler());
+ socket1.async_read_some(mutable_buffers, read_some_handler());
+ socket1.async_read_some(null_buffers(), read_some_handler());
+ int i25 = socket1.async_read_some(buffer(mutable_char_buffer), lazy);
+ (void)i25;
+ int i26 = socket1.async_read_some(mutable_buffers, lazy);
+ (void)i26;
+ int i27 = socket1.async_read_some(null_buffers(), lazy);
+ (void)i27;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_tcp_socket_compile
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_socket_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the ip::tcp::socket class.
+
+namespace ip_tcp_socket_runtime {
+
+static const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void handle_read_noop(const boost::system::error_code& err,
+ size_t bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(!err);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void handle_write_noop(const boost::system::error_code& err,
+ size_t bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(!err);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void handle_read(const boost::system::error_code& err,
+ size_t bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(!err);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+}
+
+void handle_write(const boost::system::error_code& err,
+ size_t bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(!err);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+}
+
+void handle_read_cancel(const boost::system::error_code& err,
+ size_t bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(err == boost::asio::error::operation_aborted);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void handle_read_eof(const boost::system::error_code& err,
+ size_t bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(err == boost::asio::error::eof);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void test()
+{
+ using namespace std; // For memcmp.
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ io_context ioc;
+
+ ip::tcp::acceptor acceptor(ioc, ip::tcp::endpoint(ip::tcp::v4(), 0));
+ ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+ server_endpoint.address(ip::address_v4::loopback());
+
+ ip::tcp::socket client_side_socket(ioc);
+ ip::tcp::socket server_side_socket(ioc);
+
+ client_side_socket.connect(server_endpoint);
+ acceptor.accept(server_side_socket);
+
+ // No-op read.
+
+ bool read_noop_completed = false;
+ client_side_socket.async_read_some(
+ boost::asio::mutable_buffer(0, 0),
+ bindns::bind(handle_read_noop,
+ _1, _2, &read_noop_completed));
+
+ ioc.run();
+ BOOST_ASIO_CHECK(read_noop_completed);
+
+ // No-op write.
+
+ bool write_noop_completed = false;
+ client_side_socket.async_write_some(
+ boost::asio::const_buffer(0, 0),
+ bindns::bind(handle_write_noop,
+ _1, _2, &write_noop_completed));
+
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(write_noop_completed);
+
+ // Read and write to transfer data.
+
+ char read_buffer[sizeof(write_data)];
+ bool read_completed = false;
+ boost::asio::async_read(client_side_socket,
+ boost::asio::buffer(read_buffer),
+ bindns::bind(handle_read,
+ _1, _2, &read_completed));
+
+ bool write_completed = false;
+ boost::asio::async_write(server_side_socket,
+ boost::asio::buffer(write_data),
+ bindns::bind(handle_write,
+ _1, _2, &write_completed));
+
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(read_completed);
+ BOOST_ASIO_CHECK(write_completed);
+ BOOST_ASIO_CHECK(memcmp(read_buffer, write_data, sizeof(write_data)) == 0);
+
+ // Cancelled read.
+
+ bool read_cancel_completed = false;
+ boost::asio::async_read(server_side_socket,
+ boost::asio::buffer(read_buffer),
+ bindns::bind(handle_read_cancel,
+ _1, _2, &read_cancel_completed));
+
+ ioc.restart();
+ ioc.poll();
+ BOOST_ASIO_CHECK(!read_cancel_completed);
+
+ server_side_socket.cancel();
+
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(read_cancel_completed);
+
+ // A read when the peer closes socket should fail with eof.
+
+ bool read_eof_completed = false;
+ boost::asio::async_read(client_side_socket,
+ boost::asio::buffer(read_buffer),
+ bindns::bind(handle_read_eof,
+ _1, _2, &read_eof_completed));
+
+ server_side_socket.close();
+
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(read_eof_completed);
+}
+
+} // namespace ip_tcp_socket_runtime
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_acceptor_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::tcp::acceptor compile and link correctly. Runtime failures are ignored.
+
+namespace ip_tcp_acceptor_compile {
+
+struct wait_handler
+{
+ wait_handler() {}
+ void operator()(const boost::system::error_code&) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ wait_handler(wait_handler&&) {}
+private:
+ wait_handler(const wait_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct accept_handler
+{
+ accept_handler() {}
+ void operator()(const boost::system::error_code&) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ accept_handler(accept_handler&&) {}
+private:
+ accept_handler(const accept_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+struct move_accept_handler
+{
+ move_accept_handler() {}
+ void operator()(
+ const boost::system::error_code&, boost::asio::ip::tcp::socket) {}
+ move_accept_handler(move_accept_handler&&) {}
+private:
+ move_accept_handler(const move_accept_handler&) {}
+};
+
+struct move_accept_ioc_handler
+{
+ move_accept_ioc_handler() {}
+ void operator()(const boost::system::error_code&,
+ boost::asio::basic_stream_socket<boost::asio::ip::tcp,
+ boost::asio::io_context::executor_type>) {}
+ move_accept_ioc_handler(move_accept_handler&&) {}
+private:
+ move_accept_ioc_handler(const move_accept_handler&) {}
+};
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ ip::tcp::socket peer_socket1(ioc);
+ boost::asio::basic_stream_socket<ip::tcp,
+ io_context::executor_type> peer_socket2(ioc);
+ ip::tcp::endpoint peer_endpoint;
+ archetypes::settable_socket_option<void> settable_socket_option1;
+ archetypes::settable_socket_option<int> settable_socket_option2;
+ archetypes::settable_socket_option<double> settable_socket_option3;
+ archetypes::gettable_socket_option<void> gettable_socket_option1;
+ archetypes::gettable_socket_option<int> gettable_socket_option2;
+ archetypes::gettable_socket_option<double> gettable_socket_option3;
+ archetypes::io_control_command io_control_command;
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_socket_acceptor constructors.
+
+ ip::tcp::acceptor acceptor1(ioc);
+ ip::tcp::acceptor acceptor2(ioc, ip::tcp::v4());
+ ip::tcp::acceptor acceptor3(ioc, ip::tcp::v6());
+ ip::tcp::acceptor acceptor4(ioc, ip::tcp::endpoint(ip::tcp::v4(), 0));
+ ip::tcp::acceptor acceptor5(ioc, ip::tcp::endpoint(ip::tcp::v6(), 0));
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::tcp::acceptor::native_handle_type native_acceptor1
+ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ip::tcp::acceptor acceptor6(ioc, ip::tcp::v4(), native_acceptor1);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ ip::tcp::acceptor acceptor7(ioc_ex);
+ ip::tcp::acceptor acceptor8(ioc_ex, ip::tcp::v4());
+ ip::tcp::acceptor acceptor9(ioc_ex, ip::tcp::v6());
+ ip::tcp::acceptor acceptor10(ioc_ex, ip::tcp::endpoint(ip::tcp::v4(), 0));
+ ip::tcp::acceptor acceptor11(ioc_ex, ip::tcp::endpoint(ip::tcp::v6(), 0));
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::tcp::acceptor::native_handle_type native_acceptor2
+ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ip::tcp::acceptor acceptor12(ioc_ex, ip::tcp::v4(), native_acceptor2);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ ip::tcp::acceptor acceptor13(std::move(acceptor5));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_socket_acceptor operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ acceptor1 = ip::tcp::acceptor(ioc);
+ acceptor1 = std::move(acceptor2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ ip::tcp::acceptor::executor_type ex = acceptor1.get_executor();
+ (void)ex;
+
+ // basic_socket_acceptor functions.
+
+ acceptor1.open(ip::tcp::v4());
+ acceptor1.open(ip::tcp::v6());
+ acceptor1.open(ip::tcp::v4(), ec);
+ acceptor1.open(ip::tcp::v6(), ec);
+
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::tcp::acceptor::native_handle_type native_acceptor3
+ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ acceptor1.assign(ip::tcp::v4(), native_acceptor3);
+ ip::tcp::acceptor::native_handle_type native_acceptor4
+ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ acceptor1.assign(ip::tcp::v4(), native_acceptor4, ec);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ bool is_open = acceptor1.is_open();
+ (void)is_open;
+
+ acceptor1.close();
+ acceptor1.close(ec);
+
+ acceptor1.release();
+ acceptor1.release(ec);
+
+ ip::tcp::acceptor::native_handle_type native_acceptor5
+ = acceptor1.native_handle();
+ (void)native_acceptor5;
+
+ acceptor1.cancel();
+ acceptor1.cancel(ec);
+
+ acceptor1.bind(ip::tcp::endpoint(ip::tcp::v4(), 0));
+ acceptor1.bind(ip::tcp::endpoint(ip::tcp::v6(), 0));
+ acceptor1.bind(ip::tcp::endpoint(ip::tcp::v4(), 0), ec);
+ acceptor1.bind(ip::tcp::endpoint(ip::tcp::v6(), 0), ec);
+
+ acceptor1.set_option(settable_socket_option1);
+ acceptor1.set_option(settable_socket_option1, ec);
+ acceptor1.set_option(settable_socket_option2);
+ acceptor1.set_option(settable_socket_option2, ec);
+ acceptor1.set_option(settable_socket_option3);
+ acceptor1.set_option(settable_socket_option3, ec);
+
+ acceptor1.get_option(gettable_socket_option1);
+ acceptor1.get_option(gettable_socket_option1, ec);
+ acceptor1.get_option(gettable_socket_option2);
+ acceptor1.get_option(gettable_socket_option2, ec);
+ acceptor1.get_option(gettable_socket_option3);
+ acceptor1.get_option(gettable_socket_option3, ec);
+
+ acceptor1.io_control(io_control_command);
+ acceptor1.io_control(io_control_command, ec);
+
+ bool non_blocking1 = acceptor1.non_blocking();
+ (void)non_blocking1;
+ acceptor1.non_blocking(true);
+ acceptor1.non_blocking(false, ec);
+
+ bool non_blocking2 = acceptor1.native_non_blocking();
+ (void)non_blocking2;
+ acceptor1.native_non_blocking(true);
+ acceptor1.native_non_blocking(false, ec);
+
+ ip::tcp::endpoint endpoint1 = acceptor1.local_endpoint();
+ (void)endpoint1;
+ ip::tcp::endpoint endpoint2 = acceptor1.local_endpoint(ec);
+ (void)endpoint2;
+
+ acceptor1.wait(socket_base::wait_read);
+ acceptor1.wait(socket_base::wait_write, ec);
+
+ acceptor1.async_wait(socket_base::wait_read, wait_handler());
+ int i1 = acceptor1.async_wait(socket_base::wait_write, lazy);
+ (void)i1;
+
+ acceptor1.accept(peer_socket1);
+ acceptor1.accept(peer_socket1, ec);
+ acceptor1.accept(peer_socket1, peer_endpoint);
+ acceptor1.accept(peer_socket1, peer_endpoint, ec);
+
+ acceptor1.accept(peer_socket2);
+ acceptor1.accept(peer_socket2, ec);
+ acceptor1.accept(peer_socket2, peer_endpoint);
+ acceptor1.accept(peer_socket2, peer_endpoint, ec);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ peer_socket1 = acceptor1.accept();
+ peer_socket1 = acceptor1.accept(ioc);
+ peer_socket1 = acceptor1.accept(ioc_ex);
+ peer_socket1 = acceptor1.accept(peer_endpoint);
+ peer_socket1 = acceptor1.accept(ioc, peer_endpoint);
+ peer_socket1 = acceptor1.accept(ioc_ex, peer_endpoint);
+ (void)peer_socket1;
+
+ peer_socket2 = acceptor1.accept(ioc);
+ peer_socket2 = acceptor1.accept(ioc_ex);
+ peer_socket2 = acceptor1.accept(ioc, peer_endpoint);
+ peer_socket2 = acceptor1.accept(ioc_ex, peer_endpoint);
+ (void)peer_socket2;
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ acceptor1.async_accept(peer_socket1, accept_handler());
+ acceptor1.async_accept(peer_socket1, peer_endpoint, accept_handler());
+ int i2 = acceptor1.async_accept(peer_socket1, lazy);
+ (void)i2;
+ int i3 = acceptor1.async_accept(peer_socket1, peer_endpoint, lazy);
+ (void)i3;
+
+ acceptor1.async_accept(peer_socket2, accept_handler());
+ acceptor1.async_accept(peer_socket2, peer_endpoint, accept_handler());
+ int i4 = acceptor1.async_accept(peer_socket2, lazy);
+ (void)i4;
+ int i5 = acceptor1.async_accept(peer_socket2, peer_endpoint, lazy);
+ (void)i5;
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ acceptor1.async_accept(move_accept_handler());
+ acceptor1.async_accept(ioc, move_accept_handler());
+ acceptor1.async_accept(ioc_ex, move_accept_handler());
+ acceptor1.async_accept(ioc_ex, move_accept_ioc_handler());
+ acceptor1.async_accept(peer_endpoint, move_accept_handler());
+ acceptor1.async_accept(ioc, peer_endpoint, move_accept_handler());
+ acceptor1.async_accept(ioc_ex, peer_endpoint, move_accept_handler());
+ acceptor1.async_accept(ioc_ex, peer_endpoint, move_accept_ioc_handler());
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_tcp_acceptor_compile
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_acceptor_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the ip::tcp::acceptor
+// class.
+
+namespace ip_tcp_acceptor_runtime {
+
+void handle_accept(const boost::system::error_code& err)
+{
+ BOOST_ASIO_CHECK(!err);
+}
+
+void handle_connect(const boost::system::error_code& err)
+{
+ BOOST_ASIO_CHECK(!err);
+}
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ io_context ioc;
+
+ ip::tcp::acceptor acceptor(ioc, ip::tcp::endpoint(ip::tcp::v4(), 0));
+ ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+ server_endpoint.address(ip::address_v4::loopback());
+
+ ip::tcp::socket client_side_socket(ioc);
+ ip::tcp::socket server_side_socket(ioc);
+
+ client_side_socket.connect(server_endpoint);
+ acceptor.accept(server_side_socket);
+
+ client_side_socket.close();
+ server_side_socket.close();
+
+ client_side_socket.connect(server_endpoint);
+ ip::tcp::endpoint client_endpoint;
+ acceptor.accept(server_side_socket, client_endpoint);
+
+ ip::tcp::endpoint client_side_local_endpoint
+ = client_side_socket.local_endpoint();
+ BOOST_ASIO_CHECK(client_side_local_endpoint.port() == client_endpoint.port());
+
+ ip::tcp::endpoint server_side_remote_endpoint
+ = server_side_socket.remote_endpoint();
+ BOOST_ASIO_CHECK(server_side_remote_endpoint.port()
+ == client_endpoint.port());
+
+ client_side_socket.close();
+ server_side_socket.close();
+
+ acceptor.async_accept(server_side_socket, &handle_accept);
+ client_side_socket.async_connect(server_endpoint, &handle_connect);
+
+ ioc.run();
+
+ client_side_socket.close();
+ server_side_socket.close();
+
+ acceptor.async_accept(server_side_socket, client_endpoint, &handle_accept);
+ client_side_socket.async_connect(server_endpoint, &handle_connect);
+
+ ioc.restart();
+ ioc.run();
+
+ client_side_local_endpoint = client_side_socket.local_endpoint();
+ BOOST_ASIO_CHECK(client_side_local_endpoint.port() == client_endpoint.port());
+
+ server_side_remote_endpoint = server_side_socket.remote_endpoint();
+ BOOST_ASIO_CHECK(server_side_remote_endpoint.port()
+ == client_endpoint.port());
+}
+
+} // namespace ip_tcp_acceptor_runtime
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_resolver_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::tcp::resolver compile and link correctly. Runtime failures are ignored.
+
+namespace ip_tcp_resolver_compile {
+
+struct resolve_handler
+{
+ resolve_handler() {}
+ void operator()(const boost::system::error_code&,
+ boost::asio::ip::tcp::resolver::results_type) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ resolve_handler(resolve_handler&&) {}
+private:
+ resolve_handler(const resolve_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+struct legacy_resolve_handler
+{
+ legacy_resolve_handler() {}
+ void operator()(const boost::system::error_code&,
+ boost::asio::ip::tcp::resolver::iterator) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ legacy_resolve_handler(legacy_resolve_handler&&) {}
+private:
+ legacy_resolve_handler(const legacy_resolve_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::tcp::resolver::query q(ip::tcp::v4(), "localhost", "0");
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::tcp::endpoint e(ip::address_v4::loopback(), 0);
+
+ // basic_resolver constructors.
+
+ ip::tcp::resolver resolver(ioc);
+ ip::tcp::resolver resolver2(ioc_ex);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ ip::tcp::resolver resolver3(std::move(resolver));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_resolver operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ resolver = ip::tcp::resolver(ioc);
+ resolver = std::move(resolver3);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ ip::tcp::resolver::executor_type ex = resolver.get_executor();
+ (void)ex;
+
+ // basic_resolver functions.
+
+ resolver.cancel();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::tcp::resolver::results_type results1 = resolver.resolve(q);
+ (void)results1;
+
+ ip::tcp::resolver::results_type results2 = resolver.resolve(q, ec);
+ (void)results2;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ ip::tcp::resolver::results_type results3 = resolver.resolve("", "");
+ (void)results3;
+
+ ip::tcp::resolver::results_type results4 = resolver.resolve("", "", ec);
+ (void)results4;
+
+ ip::tcp::resolver::results_type results5 =
+ resolver.resolve("", "", ip::tcp::resolver::flags());
+ (void)results5;
+
+ ip::tcp::resolver::results_type results6 =
+ resolver.resolve("", "", ip::tcp::resolver::flags(), ec);
+ (void)results6;
+
+ ip::tcp::resolver::results_type results7 =
+ resolver.resolve(ip::tcp::v4(), "", "");
+ (void)results7;
+
+ ip::tcp::resolver::results_type results8 =
+ resolver.resolve(ip::tcp::v4(), "", "", ec);
+ (void)results8;
+
+ ip::tcp::resolver::results_type results9 =
+ resolver.resolve(ip::tcp::v4(), "", "", ip::tcp::resolver::flags());
+ (void)results9;
+
+ ip::tcp::resolver::results_type results10 =
+ resolver.resolve(ip::tcp::v4(), "", "", ip::tcp::resolver::flags(), ec);
+ (void)results10;
+
+ ip::tcp::resolver::results_type results11 = resolver.resolve(e);
+ (void)results11;
+
+ ip::tcp::resolver::results_type results12 = resolver.resolve(e, ec);
+ (void)results12;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ resolver.async_resolve(q, resolve_handler());
+ resolver.async_resolve(q, legacy_resolve_handler());
+ int i1 = resolver.async_resolve(q, lazy);
+ (void)i1;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ resolver.async_resolve("", "", resolve_handler());
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ resolver.async_resolve("", "", legacy_resolve_handler());
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ int i2 = resolver.async_resolve("", "", lazy);
+ (void)i2;
+
+ resolver.async_resolve("", "",
+ ip::tcp::resolver::flags(), resolve_handler());
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ resolver.async_resolve("", "",
+ ip::tcp::resolver::flags(), legacy_resolve_handler());
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ int i3 = resolver.async_resolve("", "",
+ ip::tcp::resolver::flags(), lazy);
+ (void)i3;
+
+ resolver.async_resolve(ip::tcp::v4(), "", "", resolve_handler());
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ resolver.async_resolve(ip::tcp::v4(), "", "", legacy_resolve_handler());
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ int i4 = resolver.async_resolve(ip::tcp::v4(), "", "", lazy);
+ (void)i4;
+
+ resolver.async_resolve(ip::tcp::v4(),
+ "", "", ip::tcp::resolver::flags(), resolve_handler());
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ resolver.async_resolve(ip::tcp::v4(),
+ "", "", ip::tcp::resolver::flags(), legacy_resolve_handler());
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ int i5 = resolver.async_resolve(ip::tcp::v4(),
+ "", "", ip::tcp::resolver::flags(), lazy);
+ (void)i5;
+
+ resolver.async_resolve(e, resolve_handler());
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ resolver.async_resolve(e, legacy_resolve_handler());
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ int i6 = resolver.async_resolve(e, lazy);
+ (void)i6;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_tcp_resolver_compile
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_resolver_entry_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::tcp::resolver::entry compile and link correctly. Runtime failures are
+// ignored.
+
+namespace ip_tcp_resolver_entry_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+ const ip::tcp::endpoint endpoint;
+ const std::string host_name;
+ const std::string service_name;
+ const std::allocator<char> alloc;
+
+ try
+ {
+ // basic_resolver_entry constructors.
+
+ const ip::basic_resolver_entry<ip::tcp> entry1;
+ ip::basic_resolver_entry<ip::tcp> entry2(endpoint, host_name, service_name);
+ ip::basic_resolver_entry<ip::tcp> entry3(entry1);
+#if defined(BOOST_ASIO_HAS_MOVE)
+ ip::basic_resolver_entry<ip::tcp> entry4(std::move(entry2));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_resolver_entry functions.
+
+ ip::tcp::endpoint e1 = entry1.endpoint();
+ (void)e1;
+
+ ip::tcp::endpoint e2 = entry1;
+ (void)e2;
+
+ std::string s1 = entry1.host_name();
+ (void)s1;
+
+ std::string s2 = entry1.host_name(alloc);
+ (void)s2;
+
+ std::string s3 = entry1.service_name();
+ (void)s3;
+
+ std::string s4 = entry1.service_name(alloc);
+ (void)s4;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_tcp_resolver_entry_compile
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_iostream_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public types and member functions on the
+// class ip::tcp::iostream compile and link correctly. Runtime failures are
+// ignored.
+
+namespace ip_tcp_iostream_compile {
+
+void test()
+{
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ boost::asio::io_context ioc;
+ boost::asio::ip::tcp::socket sock(ioc);
+
+ // basic_socket_iostream typedefs.
+
+ (void)static_cast<ip::tcp::iostream::protocol_type*>(0);
+ (void)static_cast<ip::tcp::iostream::endpoint_type*>(0);
+ (void)static_cast<ip::tcp::iostream::clock_type*>(0);
+ (void)static_cast<ip::tcp::iostream::time_point*>(0);
+ (void)static_cast<ip::tcp::iostream::duration*>(0);
+ (void)static_cast<ip::tcp::iostream::traits_type*>(0);
+
+ // basic_socket_iostream constructors.
+
+ ip::tcp::iostream ios1;
+
+#if defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE)
+ ip::tcp::iostream ios2(std::move(sock));
+#endif // defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE)
+
+ ip::tcp::iostream ios3("hostname", "service");
+
+ // basic_socket_iostream operators.
+
+#if defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE)
+ ios1 = ip::tcp::iostream();
+
+ ios2 = std::move(ios1);
+#endif // defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE)
+
+ // basic_socket_iostream members.
+
+ ios1.connect("hostname", "service");
+
+ ios1.close();
+
+ (void)static_cast<std::streambuf*>(ios1.rdbuf());
+
+ basic_socket<ip::tcp>& sref = ios1.socket();
+ (void)sref;
+
+ boost::system::error_code ec = ios1.error();
+ (void)ec;
+
+ ip::tcp::iostream::time_point tp = ios1.expiry();
+ (void)tp;
+
+ ios1.expires_at(tp);
+
+ ip::tcp::iostream::duration d;
+ ios1.expires_after(d);
+
+ // iostream operators.
+
+ int i = 0;
+ ios1 >> i;
+ ios1 << i;
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+}
+
+} // namespace ip_tcp_iostream_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/tcp",
+ BOOST_ASIO_TEST_CASE(ip_tcp_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_tcp_runtime::test)
+ BOOST_ASIO_TEST_CASE(ip_tcp_socket_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_tcp_socket_runtime::test)
+ BOOST_ASIO_TEST_CASE(ip_tcp_acceptor_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_tcp_acceptor_runtime::test)
+ BOOST_ASIO_TEST_CASE(ip_tcp_resolver_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_tcp_resolver_entry_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_tcp_resolver_entry_compile::test)
+ BOOST_ASIO_COMPILE_TEST_CASE(ip_tcp_iostream_compile::test)
+)
diff --git a/src/boost/libs/asio/test/ip/udp.cpp b/src/boost/libs/asio/test/ip/udp.cpp
new file mode 100644
index 000000000..cd2ceb536
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/udp.cpp
@@ -0,0 +1,673 @@
+//
+// udp.cpp
+// ~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/udp.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include "../unit_test.hpp"
+#include "../archetypes/async_result.hpp"
+#include "../archetypes/gettable_socket_option.hpp"
+#include "../archetypes/io_control_command.hpp"
+#include "../archetypes/settable_socket_option.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+//------------------------------------------------------------------------------
+
+// ip_udp_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::udp::socket compile and link correctly. Runtime failures are ignored.
+
+namespace ip_udp_socket_compile {
+
+struct connect_handler
+{
+ connect_handler() {}
+ void operator()(const boost::system::error_code&) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ connect_handler(connect_handler&&) {}
+private:
+ connect_handler(const connect_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct wait_handler
+{
+ wait_handler() {}
+ void operator()(const boost::system::error_code&) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ wait_handler(wait_handler&&) {}
+private:
+ wait_handler(const wait_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct send_handler
+{
+ send_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ send_handler(send_handler&&) {}
+private:
+ send_handler(const send_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct receive_handler
+{
+ receive_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ receive_handler(receive_handler&&) {}
+private:
+ receive_handler(const receive_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ socket_base::message_flags in_flags = 0;
+ archetypes::settable_socket_option<void> settable_socket_option1;
+ archetypes::settable_socket_option<int> settable_socket_option2;
+ archetypes::settable_socket_option<double> settable_socket_option3;
+ archetypes::gettable_socket_option<void> gettable_socket_option1;
+ archetypes::gettable_socket_option<int> gettable_socket_option2;
+ archetypes::gettable_socket_option<double> gettable_socket_option3;
+ archetypes::io_control_command io_control_command;
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_datagram_socket constructors.
+
+ ip::udp::socket socket1(ioc);
+ ip::udp::socket socket2(ioc, ip::udp::v4());
+ ip::udp::socket socket3(ioc, ip::udp::v6());
+ ip::udp::socket socket4(ioc, ip::udp::endpoint(ip::udp::v4(), 0));
+ ip::udp::socket socket5(ioc, ip::udp::endpoint(ip::udp::v6(), 0));
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::udp::socket::native_handle_type native_socket1
+ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ ip::udp::socket socket6(ioc, ip::udp::v4(), native_socket1);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ ip::udp::socket socket7(ioc_ex);
+ ip::udp::socket socket8(ioc_ex, ip::udp::v4());
+ ip::udp::socket socket9(ioc_ex, ip::udp::v6());
+ ip::udp::socket socket10(ioc_ex, ip::udp::endpoint(ip::udp::v4(), 0));
+ ip::udp::socket socket11(ioc_ex, ip::udp::endpoint(ip::udp::v6(), 0));
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::udp::socket::native_handle_type native_socket2
+ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ ip::udp::socket socket12(ioc_ex, ip::udp::v4(), native_socket2);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ ip::udp::socket socket13(std::move(socket6));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_datagram_socket operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ socket1 = ip::udp::socket(ioc);
+ socket1 = std::move(socket2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ ip::udp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ ip::udp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ const ip::udp::socket& socket14 = socket1;
+ const ip::udp::socket::lowest_layer_type& lowest_layer2
+ = socket14.lowest_layer();
+ (void)lowest_layer2;
+
+ socket1.open(ip::udp::v4());
+ socket1.open(ip::udp::v6());
+ socket1.open(ip::udp::v4(), ec);
+ socket1.open(ip::udp::v6(), ec);
+
+#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ip::udp::socket::native_handle_type native_socket3
+ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ socket1.assign(ip::udp::v4(), native_socket3);
+ ip::udp::socket::native_handle_type native_socket4
+ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ socket1.assign(ip::udp::v4(), native_socket4, ec);
+#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ socket1.release();
+ socket1.release(ec);
+
+ ip::udp::socket::native_handle_type native_socket5
+ = socket1.native_handle();
+ (void)native_socket5;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(ip::udp::endpoint(ip::udp::v4(), 0));
+ socket1.bind(ip::udp::endpoint(ip::udp::v6(), 0));
+ socket1.bind(ip::udp::endpoint(ip::udp::v4(), 0), ec);
+ socket1.bind(ip::udp::endpoint(ip::udp::v6(), 0), ec);
+
+ socket1.connect(ip::udp::endpoint(ip::udp::v4(), 0));
+ socket1.connect(ip::udp::endpoint(ip::udp::v6(), 0));
+ socket1.connect(ip::udp::endpoint(ip::udp::v4(), 0), ec);
+ socket1.connect(ip::udp::endpoint(ip::udp::v6(), 0), ec);
+
+ socket1.async_connect(ip::udp::endpoint(ip::udp::v4(), 0),
+ connect_handler());
+ socket1.async_connect(ip::udp::endpoint(ip::udp::v6(), 0),
+ connect_handler());
+ int i1 = socket1.async_connect(ip::udp::endpoint(ip::udp::v4(), 0), lazy);
+ (void)i1;
+ int i2 = socket1.async_connect(ip::udp::endpoint(ip::udp::v6(), 0), lazy);
+ (void)i2;
+
+ socket1.set_option(settable_socket_option1);
+ socket1.set_option(settable_socket_option1, ec);
+ socket1.set_option(settable_socket_option2);
+ socket1.set_option(settable_socket_option2, ec);
+ socket1.set_option(settable_socket_option3);
+ socket1.set_option(settable_socket_option3, ec);
+
+ socket1.get_option(gettable_socket_option1);
+ socket1.get_option(gettable_socket_option1, ec);
+ socket1.get_option(gettable_socket_option2);
+ socket1.get_option(gettable_socket_option2, ec);
+ socket1.get_option(gettable_socket_option3);
+ socket1.get_option(gettable_socket_option3, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ bool non_blocking1 = socket1.non_blocking();
+ (void)non_blocking1;
+ socket1.non_blocking(true);
+ socket1.non_blocking(false, ec);
+
+ bool non_blocking2 = socket1.native_non_blocking();
+ (void)non_blocking2;
+ socket1.native_non_blocking(true);
+ socket1.native_non_blocking(false, ec);
+
+ ip::udp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ ip::udp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ ip::udp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ ip::udp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ socket1.wait(socket_base::wait_read);
+ socket1.wait(socket_base::wait_write, ec);
+
+ socket1.async_wait(socket_base::wait_read, wait_handler());
+ int i3 = socket1.async_wait(socket_base::wait_write, lazy);
+ (void)i3;
+
+ // basic_datagram_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer));
+ socket1.send(buffer(const_char_buffer));
+ socket1.send(null_buffers());
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), send_handler());
+ socket1.async_send(buffer(const_char_buffer), send_handler());
+ socket1.async_send(null_buffers(), send_handler());
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler());
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler());
+ socket1.async_send(null_buffers(), in_flags, send_handler());
+ int i4 = socket1.async_send(buffer(mutable_char_buffer), lazy);
+ (void)i4;
+ int i5 = socket1.async_send(buffer(const_char_buffer), lazy);
+ (void)i5;
+ int i6 = socket1.async_send(null_buffers(), lazy);
+ (void)i6;
+ int i7 = socket1.async_send(buffer(mutable_char_buffer), in_flags, lazy);
+ (void)i7;
+ int i8 = socket1.async_send(buffer(const_char_buffer), in_flags, lazy);
+ (void)i8;
+ int i9 = socket1.async_send(null_buffers(), in_flags, lazy);
+ (void)i9;
+
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0));
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0));
+ socket1.send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0));
+ socket1.send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0));
+ socket1.send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v4(), 0));
+ socket1.send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v6(), 0));
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags);
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags);
+ socket1.send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags);
+ socket1.send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags);
+ socket1.send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags);
+ socket1.send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags);
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, ec);
+ socket1.send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, ec);
+ socket1.send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, ec);
+ socket1.send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, ec);
+ socket1.send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, ec);
+ socket1.send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, ec);
+
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), send_handler());
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), send_handler());
+ socket1.async_send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), send_handler());
+ socket1.async_send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), send_handler());
+ socket1.async_send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v4(), 0), send_handler());
+ socket1.async_send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v6(), 0), send_handler());
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, send_handler());
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, send_handler());
+ socket1.async_send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, send_handler());
+ socket1.async_send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, send_handler());
+ socket1.async_send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, send_handler());
+ socket1.async_send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, send_handler());
+ int i10 = socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), lazy);
+ (void)i10;
+ int i11 = socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), lazy);
+ (void)i11;
+ int i12 = socket1.async_send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), lazy);
+ (void)i12;
+ int i13 = socket1.async_send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), lazy);
+ (void)i13;
+ int i14 = socket1.async_send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v4(), 0), lazy);
+ (void)i14;
+ int i15 = socket1.async_send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v6(), 0), lazy);
+ (void)i15;
+ int i16 = socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, lazy);
+ (void)i16;
+ int i17 = socket1.async_send_to(buffer(mutable_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, lazy);
+ (void)i17;
+ int i18 = socket1.async_send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, lazy);
+ (void)i18;
+ int i19 = socket1.async_send_to(buffer(const_char_buffer),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, lazy);
+ (void)i19;
+ int i20 = socket1.async_send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v4(), 0), in_flags, lazy);
+ (void)i20;
+ int i21 = socket1.async_send_to(null_buffers(),
+ ip::udp::endpoint(ip::udp::v6(), 0), in_flags, lazy);
+ (void)i21;
+
+ socket1.receive(buffer(mutable_char_buffer));
+ socket1.receive(null_buffers());
+ socket1.receive(buffer(mutable_char_buffer), in_flags);
+ socket1.receive(null_buffers(), in_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.receive(null_buffers(), in_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), receive_handler());
+ socket1.async_receive(null_buffers(), receive_handler());
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ receive_handler());
+ socket1.async_receive(null_buffers(), in_flags, receive_handler());
+ int i22 = socket1.async_receive(buffer(mutable_char_buffer), lazy);
+ (void)i22;
+ int i23 = socket1.async_receive(null_buffers(), lazy);
+ (void)i23;
+ int i24 = socket1.async_receive(buffer(mutable_char_buffer),
+ in_flags, lazy);
+ (void)i24;
+ int i25 = socket1.async_receive(null_buffers(), in_flags, lazy);
+ (void)i25;
+
+ ip::udp::endpoint endpoint;
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint);
+ socket1.receive_from(null_buffers(), endpoint);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags);
+ socket1.receive_from(null_buffers(), endpoint, in_flags);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags, ec);
+ socket1.receive_from(null_buffers(), endpoint, in_flags, ec);
+
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, receive_handler());
+ socket1.async_receive_from(null_buffers(),
+ endpoint, receive_handler());
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, in_flags, receive_handler());
+ socket1.async_receive_from(null_buffers(),
+ endpoint, in_flags, receive_handler());
+ int i26 = socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, lazy);
+ (void)i26;
+ int i27 = socket1.async_receive_from(null_buffers(),
+ endpoint, lazy);
+ (void)i27;
+ int i28 = socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, in_flags, lazy);
+ (void)i28;
+ int i29 = socket1.async_receive_from(null_buffers(),
+ endpoint, in_flags, lazy);
+ (void)i29;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_udp_socket_compile
+
+//------------------------------------------------------------------------------
+
+// ip_udp_socket_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the ip::udp::socket class.
+
+namespace ip_udp_socket_runtime {
+
+void handle_send(size_t expected_bytes_sent,
+ const boost::system::error_code& err, size_t bytes_sent)
+{
+ BOOST_ASIO_CHECK(!err);
+ BOOST_ASIO_CHECK(expected_bytes_sent == bytes_sent);
+}
+
+void handle_recv(size_t expected_bytes_recvd,
+ const boost::system::error_code& err, size_t bytes_recvd)
+{
+ BOOST_ASIO_CHECK(!err);
+ BOOST_ASIO_CHECK(expected_bytes_recvd == bytes_recvd);
+}
+
+void test()
+{
+ using namespace std; // For memcmp and memset.
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ io_context ioc;
+
+ ip::udp::socket s1(ioc, ip::udp::endpoint(ip::udp::v4(), 0));
+ ip::udp::endpoint target_endpoint = s1.local_endpoint();
+ target_endpoint.address(ip::address_v4::loopback());
+
+ ip::udp::socket s2(ioc);
+ s2.open(ip::udp::v4());
+ s2.bind(ip::udp::endpoint(ip::udp::v4(), 0));
+ char send_msg[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ s2.send_to(buffer(send_msg, sizeof(send_msg)), target_endpoint);
+
+ char recv_msg[sizeof(send_msg)];
+ ip::udp::endpoint sender_endpoint;
+ size_t bytes_recvd = s1.receive_from(buffer(recv_msg, sizeof(recv_msg)),
+ sender_endpoint);
+
+ BOOST_ASIO_CHECK(bytes_recvd == sizeof(send_msg));
+ BOOST_ASIO_CHECK(memcmp(send_msg, recv_msg, sizeof(send_msg)) == 0);
+
+ memset(recv_msg, 0, sizeof(recv_msg));
+
+ target_endpoint = sender_endpoint;
+ s1.async_send_to(buffer(send_msg, sizeof(send_msg)), target_endpoint,
+ bindns::bind(handle_send, sizeof(send_msg), _1, _2));
+ s2.async_receive_from(buffer(recv_msg, sizeof(recv_msg)), sender_endpoint,
+ bindns::bind(handle_recv, sizeof(recv_msg), _1, _2));
+
+ ioc.run();
+
+ BOOST_ASIO_CHECK(memcmp(send_msg, recv_msg, sizeof(send_msg)) == 0);
+}
+
+} // namespace ip_udp_socket_runtime
+
+//------------------------------------------------------------------------------
+
+// ip_udp_resolver_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ip::udp::resolver compile and link correctly. Runtime failures are ignored.
+
+namespace ip_udp_resolver_compile {
+
+struct resolve_handler
+{
+ resolve_handler() {}
+ void operator()(const boost::system::error_code&,
+ boost::asio::ip::udp::resolver::results_type) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ resolve_handler(resolve_handler&&) {}
+private:
+ resolve_handler(const resolve_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::udp::resolver::query q(ip::udp::v4(), "localhost", "0");
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::udp::endpoint e(ip::address_v4::loopback(), 0);
+
+ // basic_resolver constructors.
+
+ ip::udp::resolver resolver(ioc);
+ ip::udp::resolver resolver2(ioc_ex);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ ip::udp::resolver resolver3(std::move(resolver));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_resolver operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ resolver = ip::udp::resolver(ioc);
+ resolver = std::move(resolver3);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ ip::udp::resolver::executor_type ex = resolver.get_executor();
+ (void)ex;
+
+ // basic_resolver functions.
+
+ resolver.cancel();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ ip::udp::resolver::results_type results1 = resolver.resolve(q);
+ (void)results1;
+
+ ip::udp::resolver::results_type results2 = resolver.resolve(q, ec);
+ (void)results2;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ ip::udp::resolver::results_type results3 = resolver.resolve("", "");
+ (void)results3;
+
+ ip::udp::resolver::results_type results4 = resolver.resolve("", "", ec);
+ (void)results4;
+
+ ip::udp::resolver::results_type results5 =
+ resolver.resolve("", "", ip::udp::resolver::flags());
+ (void)results5;
+
+ ip::udp::resolver::results_type results6 =
+ resolver.resolve("", "", ip::udp::resolver::flags(), ec);
+ (void)results6;
+
+ ip::udp::resolver::results_type results7 =
+ resolver.resolve(ip::udp::v4(), "", "");
+ (void)results7;
+
+ ip::udp::resolver::results_type results8 =
+ resolver.resolve(ip::udp::v4(), "", "", ec);
+ (void)results8;
+
+ ip::udp::resolver::results_type results9 =
+ resolver.resolve(ip::udp::v4(), "", "", ip::udp::resolver::flags());
+ (void)results9;
+
+ ip::udp::resolver::results_type results10 =
+ resolver.resolve(ip::udp::v4(), "", "", ip::udp::resolver::flags(), ec);
+ (void)results10;
+
+ ip::udp::resolver::results_type results11 = resolver.resolve(e);
+ (void)results11;
+
+ ip::udp::resolver::results_type results12 = resolver.resolve(e, ec);
+ (void)results12;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ resolver.async_resolve(q, resolve_handler());
+ int i1 = resolver.async_resolve(q, lazy);
+ (void)i1;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ resolver.async_resolve("", "", resolve_handler());
+ int i2 = resolver.async_resolve("", "", lazy);
+ (void)i2;
+
+ resolver.async_resolve("", "",
+ ip::udp::resolver::flags(), resolve_handler());
+ int i3 = resolver.async_resolve("", "",
+ ip::udp::resolver::flags(), lazy);
+ (void)i3;
+
+ resolver.async_resolve(ip::udp::v4(), "", "", resolve_handler());
+ int i4 = resolver.async_resolve(ip::udp::v4(), "", "", lazy);
+ (void)i4;
+
+ resolver.async_resolve(ip::udp::v4(),
+ "", "", ip::udp::resolver::flags(), resolve_handler());
+ int i5 = resolver.async_resolve(ip::udp::v4(),
+ "", "", ip::udp::resolver::flags(), lazy);
+ (void)i5;
+
+ resolver.async_resolve(e, resolve_handler());
+ int i6 = resolver.async_resolve(e, lazy);
+ (void)i6;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_udp_resolver_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/udp",
+ BOOST_ASIO_TEST_CASE(ip_udp_socket_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_udp_socket_runtime::test)
+ BOOST_ASIO_TEST_CASE(ip_udp_resolver_compile::test)
+)
diff --git a/src/boost/libs/asio/test/ip/unicast.cpp b/src/boost/libs/asio/test/ip/unicast.cpp
new file mode 100644
index 000000000..1a48fab11
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/unicast.cpp
@@ -0,0 +1,171 @@
+//
+// unicast.cpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/unicast.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// ip_unicast_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all nested classes, enums and constants in
+// ip::unicast compile and link correctly. Runtime failures are ignored.
+
+namespace ip_unicast_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ ip::udp::socket sock(ioc);
+
+ // hops class.
+
+ ip::unicast::hops hops1(1024);
+ sock.set_option(hops1);
+ ip::unicast::hops hops2;
+ sock.get_option(hops2);
+ hops1 = 1;
+ (void)static_cast<int>(hops1.value());
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_unicast_compile
+
+//------------------------------------------------------------------------------
+
+// ip_unicast_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the socket options defined
+// in the ip::unicast namespace.
+
+namespace ip_unicast_runtime {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ io_context ioc;
+ boost::system::error_code ec;
+
+ ip::udp::endpoint ep_v4(ip::address_v4::loopback(), 0);
+ ip::udp::socket sock_v4(ioc);
+ sock_v4.open(ep_v4.protocol(), ec);
+ sock_v4.bind(ep_v4, ec);
+ bool have_v4 = !ec;
+
+ ip::udp::endpoint ep_v6(ip::address_v6::loopback(), 0);
+ ip::udp::socket sock_v6(ioc);
+ sock_v6.open(ep_v6.protocol(), ec);
+ sock_v6.bind(ep_v6, ec);
+ bool have_v6 = !ec;
+
+ BOOST_ASIO_CHECK(have_v4 || have_v6);
+
+ // hops class.
+
+ if (have_v4)
+ {
+ ip::unicast::hops hops1(1);
+ BOOST_ASIO_CHECK(hops1.value() == 1);
+ sock_v4.set_option(hops1, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK(!ec);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ ip::unicast::hops hops2;
+ sock_v4.get_option(hops2, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(hops2.value() == 1);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ ip::unicast::hops hops3(255);
+ BOOST_ASIO_CHECK(hops3.value() == 255);
+ sock_v4.set_option(hops3, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK(!ec);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ ip::unicast::hops hops4;
+ sock_v4.get_option(hops4, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(hops4.value() == 255);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ }
+
+ if (have_v6)
+ {
+ ip::unicast::hops hops1(1);
+ BOOST_ASIO_CHECK(hops1.value() == 1);
+ sock_v6.set_option(hops1, ec);
+ BOOST_ASIO_CHECK(!ec);
+
+ ip::unicast::hops hops2;
+ sock_v6.get_option(hops2, ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(hops2.value() == 1);
+
+ ip::unicast::hops hops3(255);
+ BOOST_ASIO_CHECK(hops3.value() == 255);
+ sock_v6.set_option(hops3, ec);
+ BOOST_ASIO_CHECK(!ec);
+
+ ip::unicast::hops hops4;
+ sock_v6.get_option(hops4, ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(hops4.value() == 255);
+ }
+}
+
+} // namespace ip_unicast_runtime
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/unicast",
+ BOOST_ASIO_TEST_CASE(ip_unicast_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_unicast_runtime::test)
+)
diff --git a/src/boost/libs/asio/test/ip/v6_only.cpp b/src/boost/libs/asio/test/ip/v6_only.cpp
new file mode 100644
index 000000000..570781266
--- /dev/null
+++ b/src/boost/libs/asio/test/ip/v6_only.cpp
@@ -0,0 +1,135 @@
+//
+// v6_only.cpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ip/v6_only.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// ip_v6_only_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that the ip::v6_only socket option compiles and
+// link correctly. Runtime failures are ignored.
+
+namespace ip_v6_only_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ ip::udp::socket sock(ioc);
+
+ // v6_only class.
+
+ ip::v6_only v6_only1(true);
+ sock.set_option(v6_only1);
+ ip::v6_only v6_only2;
+ sock.get_option(v6_only2);
+ v6_only1 = true;
+ (void)static_cast<bool>(v6_only1);
+ (void)static_cast<bool>(!v6_only1);
+ (void)static_cast<bool>(v6_only1.value());
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ip_v6_only_compile
+
+//------------------------------------------------------------------------------
+
+// ip_v6_only_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the ip::v6_only socket
+// option.
+
+namespace ip_v6_only_runtime {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ io_context ioc;
+ boost::system::error_code ec;
+
+ ip::tcp::endpoint ep_v6(ip::address_v6::loopback(), 0);
+ ip::tcp::acceptor acceptor_v6(ioc);
+ acceptor_v6.open(ep_v6.protocol(), ec);
+ acceptor_v6.bind(ep_v6, ec);
+ bool have_v6 = !ec;
+ acceptor_v6.close(ec);
+ acceptor_v6.open(ep_v6.protocol(), ec);
+
+ if (have_v6)
+ {
+ ip::v6_only v6_only1;
+ acceptor_v6.get_option(v6_only1, ec);
+ BOOST_ASIO_CHECK(!ec);
+ bool have_dual_stack = !v6_only1.value();
+
+ if (have_dual_stack)
+ {
+ ip::v6_only v6_only2(false);
+ BOOST_ASIO_CHECK(!v6_only2.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(v6_only2));
+ BOOST_ASIO_CHECK(!v6_only2);
+ acceptor_v6.set_option(v6_only2, ec);
+ BOOST_ASIO_CHECK(!ec);
+
+ ip::v6_only v6_only3;
+ acceptor_v6.get_option(v6_only3, ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(!v6_only3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(v6_only3));
+ BOOST_ASIO_CHECK(!v6_only3);
+
+ ip::v6_only v6_only4(true);
+ BOOST_ASIO_CHECK(v6_only4.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(v6_only4));
+ BOOST_ASIO_CHECK(!!v6_only4);
+ acceptor_v6.set_option(v6_only4, ec);
+ BOOST_ASIO_CHECK(!ec);
+
+ ip::v6_only v6_only5;
+ acceptor_v6.get_option(v6_only5, ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(v6_only5.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(v6_only5));
+ BOOST_ASIO_CHECK(!!v6_only5);
+ }
+ }
+}
+
+} // namespace ip_v6_only_runtime
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ip/v6_only",
+ BOOST_ASIO_TEST_CASE(ip_v6_only_compile::test)
+ BOOST_ASIO_TEST_CASE(ip_v6_only_runtime::test)
+)
diff --git a/src/boost/libs/asio/test/is_read_buffered.cpp b/src/boost/libs/asio/test/is_read_buffered.cpp
new file mode 100644
index 000000000..868c64644
--- /dev/null
+++ b/src/boost/libs/asio/test/is_read_buffered.cpp
@@ -0,0 +1,129 @@
+//
+// is_read_buffered.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/is_read_buffered.hpp>
+
+#include <boost/asio/buffered_read_stream.hpp>
+#include <boost/asio/buffered_write_stream.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include "unit_test.hpp"
+
+using namespace std; // For memcmp, memcpy and memset.
+
+class test_stream
+{
+public:
+ typedef boost::asio::io_context io_context_type;
+
+ typedef test_stream lowest_layer_type;
+
+ typedef io_context_type::executor_type executor_type;
+
+ test_stream(boost::asio::io_context& io_context)
+ : io_context_(io_context)
+ {
+ }
+
+ io_context_type& io_context()
+ {
+ return io_context_;
+ }
+
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ template <typename Const_Buffers>
+ size_t write(const Const_Buffers&)
+ {
+ return 0;
+ }
+
+ template <typename Const_Buffers>
+ size_t write(const Const_Buffers&, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ template <typename Const_Buffers, typename Handler>
+ void async_write(const Const_Buffers&, Handler handler)
+ {
+ boost::system::error_code error;
+ boost::asio::post(io_context_,
+ boost::asio::detail::bind_handler(handler, error, 0));
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read(const Mutable_Buffers&)
+ {
+ return 0;
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read(const Mutable_Buffers&, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ template <typename Mutable_Buffers, typename Handler>
+ void async_read(const Mutable_Buffers&, Handler handler)
+ {
+ boost::system::error_code error;
+ boost::asio::post(io_context_,
+ boost::asio::detail::bind_handler(handler, error, 0));
+ }
+
+private:
+ io_context_type& io_context_;
+};
+
+void is_read_buffered_test()
+{
+ BOOST_ASIO_CHECK(!boost::asio::is_read_buffered<
+ boost::asio::ip::tcp::socket>::value);
+
+ BOOST_ASIO_CHECK(!!boost::asio::is_read_buffered<
+ boost::asio::buffered_read_stream<
+ boost::asio::ip::tcp::socket> >::value);
+
+ BOOST_ASIO_CHECK(!boost::asio::is_read_buffered<
+ boost::asio::buffered_write_stream<
+ boost::asio::ip::tcp::socket> >::value);
+
+ BOOST_ASIO_CHECK(!!boost::asio::is_read_buffered<
+ boost::asio::buffered_stream<boost::asio::ip::tcp::socket> >::value);
+
+ BOOST_ASIO_CHECK(!boost::asio::is_read_buffered<test_stream>::value);
+
+ BOOST_ASIO_CHECK(!!boost::asio::is_read_buffered<
+ boost::asio::buffered_read_stream<test_stream> >::value);
+
+ BOOST_ASIO_CHECK(!boost::asio::is_read_buffered<
+ boost::asio::buffered_write_stream<test_stream> >::value);
+
+ BOOST_ASIO_CHECK(!!boost::asio::is_read_buffered<
+ boost::asio::buffered_stream<test_stream> >::value);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "is_read_buffered",
+ BOOST_ASIO_TEST_CASE(is_read_buffered_test)
+)
diff --git a/src/boost/libs/asio/test/is_write_buffered.cpp b/src/boost/libs/asio/test/is_write_buffered.cpp
new file mode 100644
index 000000000..c00c39b4a
--- /dev/null
+++ b/src/boost/libs/asio/test/is_write_buffered.cpp
@@ -0,0 +1,129 @@
+//
+// is_write_buffered.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/is_write_buffered.hpp>
+
+#include <boost/asio/buffered_read_stream.hpp>
+#include <boost/asio/buffered_write_stream.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include "unit_test.hpp"
+
+using namespace std; // For memcmp, memcpy and memset.
+
+class test_stream
+{
+public:
+ typedef boost::asio::io_context io_context_type;
+
+ typedef test_stream lowest_layer_type;
+
+ typedef io_context_type::executor_type executor_type;
+
+ test_stream(boost::asio::io_context& io_context)
+ : io_context_(io_context)
+ {
+ }
+
+ io_context_type& io_context()
+ {
+ return io_context_;
+ }
+
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ template <typename Const_Buffers>
+ size_t write(const Const_Buffers&)
+ {
+ return 0;
+ }
+
+ template <typename Const_Buffers>
+ size_t write(const Const_Buffers&, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ template <typename Const_Buffers, typename Handler>
+ void async_write(const Const_Buffers&, Handler handler)
+ {
+ boost::system::error_code error;
+ boost::asio::post(io_context_,
+ boost::asio::detail::bind_handler(handler, error, 0));
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read(const Mutable_Buffers&)
+ {
+ return 0;
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read(const Mutable_Buffers&, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ template <typename Mutable_Buffers, typename Handler>
+ void async_read(const Mutable_Buffers&, Handler handler)
+ {
+ boost::system::error_code error;
+ boost::asio::post(io_context_,
+ boost::asio::detail::bind_handler(handler, error, 0));
+ }
+
+private:
+ io_context_type& io_context_;
+};
+
+void is_write_buffered_test()
+{
+ BOOST_ASIO_CHECK(!boost::asio::is_write_buffered<
+ boost::asio::ip::tcp::socket>::value);
+
+ BOOST_ASIO_CHECK(!boost::asio::is_write_buffered<
+ boost::asio::buffered_read_stream<
+ boost::asio::ip::tcp::socket> >::value);
+
+ BOOST_ASIO_CHECK(!!boost::asio::is_write_buffered<
+ boost::asio::buffered_write_stream<
+ boost::asio::ip::tcp::socket> >::value);
+
+ BOOST_ASIO_CHECK(!!boost::asio::is_write_buffered<
+ boost::asio::buffered_stream<boost::asio::ip::tcp::socket> >::value);
+
+ BOOST_ASIO_CHECK(!boost::asio::is_write_buffered<test_stream>::value);
+
+ BOOST_ASIO_CHECK(!boost::asio::is_write_buffered<
+ boost::asio::buffered_read_stream<test_stream> >::value);
+
+ BOOST_ASIO_CHECK(!!boost::asio::is_write_buffered<
+ boost::asio::buffered_write_stream<test_stream> >::value);
+
+ BOOST_ASIO_CHECK(!!boost::asio::is_write_buffered<
+ boost::asio::buffered_stream<test_stream> >::value);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "is_write_buffered",
+ BOOST_ASIO_TEST_CASE(is_write_buffered_test)
+)
diff --git a/src/boost/libs/asio/test/latency/Jamfile.v2 b/src/boost/libs/asio/test/latency/Jamfile.v2
new file mode 100644
index 000000000..cd6c88cc3
--- /dev/null
+++ b/src/boost/libs/asio/test/latency/Jamfile.v2
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+project
+ : requirements
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+exe tcp_server : tcp_server.cpp ;
+exe tcp_client : tcp_client.cpp ;
+exe udp_server : udp_server.cpp ;
+exe udp_client : udp_client.cpp ;
diff --git a/src/boost/libs/asio/test/latency/allocator.hpp b/src/boost/libs/asio/test/latency/allocator.hpp
new file mode 100644
index 000000000..33cdfbf8f
--- /dev/null
+++ b/src/boost/libs/asio/test/latency/allocator.hpp
@@ -0,0 +1,52 @@
+//
+// allocator.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 ALLOCATOR_HPP
+#define ALLOCATOR_HPP
+
+#include <boost/aligned_storage.hpp>
+
+// Represents a single connection from a client.
+class allocator
+{
+public:
+ allocator()
+ : in_use_(false)
+ {
+ }
+
+ void* allocate(std::size_t n)
+ {
+ if (in_use_ || n >= 1024)
+ return ::operator new(n);
+ in_use_ = true;
+ return static_cast<void*>(&space_);
+ }
+
+ void deallocate(void* p)
+ {
+ if (p != static_cast<void*>(&space_))
+ ::operator delete(p);
+ else
+ in_use_ = false;
+ }
+
+private:
+ allocator(const allocator&);
+ allocator& operator=(const allocator&);
+
+ // Whether the reusable memory space is currently in use.
+ bool in_use_;
+
+ // The reusable memory space made available by the allocator.
+ boost::aligned_storage<1024>::type space_;
+};
+
+#endif // ALLOCATOR_HPP
diff --git a/src/boost/libs/asio/test/latency/high_res_clock.hpp b/src/boost/libs/asio/test/latency/high_res_clock.hpp
new file mode 100644
index 000000000..afc33ccef
--- /dev/null
+++ b/src/boost/libs/asio/test/latency/high_res_clock.hpp
@@ -0,0 +1,53 @@
+//
+// high_res_clock.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 HIGH_RES_CLOCK_HPP
+#define HIGH_RES_CLOCK_HPP
+
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS)
+
+inline boost::uint64_t high_res_clock()
+{
+ LARGE_INTEGER i;
+ QueryPerformanceCounter(&i);
+ return i.QuadPart;
+}
+
+#elif defined(__GNUC__) && defined(__x86_64__)
+
+inline boost::uint64_t high_res_clock()
+{
+ unsigned long low, high;
+ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
+ return (((boost::uint64_t)high) << 32) | low;
+}
+
+#else
+
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+inline boost::uint64_t high_res_clock()
+{
+ boost::posix_time::ptime now =
+ boost::posix_time::microsec_clock::universal_time();
+
+ boost::posix_time::ptime epoch(
+ boost::gregorian::date(1970, 1, 1),
+ boost::posix_time::seconds(0));
+
+ return (now - epoch).total_microseconds();
+}
+
+#endif
+
+#endif // HIGH_RES_CLOCK_HPP
diff --git a/src/boost/libs/asio/test/latency/tcp_client.cpp b/src/boost/libs/asio/test/latency/tcp_client.cpp
new file mode 100644
index 000000000..bdcdcf2df
--- /dev/null
+++ b/src/boost/libs/asio/test/latency/tcp_client.cpp
@@ -0,0 +1,124 @@
+//
+// tcp_client.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/shared_ptr.hpp>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+#include "high_res_clock.hpp"
+
+using boost::asio::ip::tcp;
+using boost::posix_time::ptime;
+using boost::posix_time::microsec_clock;
+
+const int num_samples = 100000;
+
+struct transfer_all
+{
+ typedef std::size_t result_type;
+ std::size_t operator()(const boost::system::error_code& ec, std::size_t)
+ {
+ return (ec && ec != boost::asio::error::would_block) ? 0 : ~0;
+ }
+};
+
+int main(int argc, char* argv[])
+{
+ if (argc != 6)
+ {
+ std::fprintf(stderr,
+ "Usage: tcp_client <ip> <port> "
+ "<nconns> <bufsize> {spin|block}\n");
+ return 1;
+ }
+
+ const char* ip = argv[1];
+ unsigned short port = static_cast<unsigned short>(std::atoi(argv[2]));
+ int num_connections = std::atoi(argv[3]);
+ std::size_t buf_size = static_cast<std::size_t>(std::atoi(argv[4]));
+ bool spin = (std::strcmp(argv[5], "spin") == 0);
+
+ boost::asio::io_context io_context;
+ std::vector<boost::shared_ptr<tcp::socket> > sockets;
+
+ for (int i = 0; i < num_connections; ++i)
+ {
+ boost::shared_ptr<tcp::socket> s(new tcp::socket(io_context));
+
+ tcp::endpoint target(boost::asio::ip::make_address(ip), port);
+ s->connect(target);
+
+ s->set_option(tcp::no_delay(true));
+
+ if (spin)
+ {
+ s->non_blocking(true);
+ }
+
+ sockets.push_back(s);
+ }
+
+ std::vector<unsigned char> write_buf(buf_size);
+ std::vector<unsigned char> read_buf(buf_size);
+
+ ptime start = microsec_clock::universal_time();
+ boost::uint64_t start_hr = high_res_clock();
+
+ boost::uint64_t samples[num_samples];
+ for (int i = 0; i < num_samples; ++i)
+ {
+ tcp::socket& socket = *sockets[i % num_connections];
+
+ boost::uint64_t t = high_res_clock();
+
+ boost::system::error_code ec;
+ boost::asio::write(socket,
+ boost::asio::buffer(write_buf),
+ transfer_all(), ec);
+
+ boost::asio::read(socket,
+ boost::asio::buffer(read_buf),
+ transfer_all(), ec);
+
+ samples[i] = high_res_clock() - t;
+ }
+
+ ptime stop = microsec_clock::universal_time();
+ boost::uint64_t stop_hr = high_res_clock();
+ boost::uint64_t elapsed_usec = (stop - start).total_microseconds();
+ boost::uint64_t elapsed_hr = stop_hr - start_hr;
+ double scale = 1.0 * elapsed_usec / elapsed_hr;
+
+ std::sort(samples, samples + num_samples);
+ std::printf(" 0.0%%\t%f\n", samples[0] * scale);
+ std::printf(" 0.1%%\t%f\n", samples[num_samples / 1000 - 1] * scale);
+ std::printf(" 1.0%%\t%f\n", samples[num_samples / 100 - 1] * scale);
+ std::printf(" 10.0%%\t%f\n", samples[num_samples / 10 - 1] * scale);
+ std::printf(" 20.0%%\t%f\n", samples[num_samples * 2 / 10 - 1] * scale);
+ std::printf(" 30.0%%\t%f\n", samples[num_samples * 3 / 10 - 1] * scale);
+ std::printf(" 40.0%%\t%f\n", samples[num_samples * 4 / 10 - 1] * scale);
+ std::printf(" 50.0%%\t%f\n", samples[num_samples * 5 / 10 - 1] * scale);
+ std::printf(" 60.0%%\t%f\n", samples[num_samples * 6 / 10 - 1] * scale);
+ std::printf(" 70.0%%\t%f\n", samples[num_samples * 7 / 10 - 1] * scale);
+ std::printf(" 80.0%%\t%f\n", samples[num_samples * 8 / 10 - 1] * scale);
+ std::printf(" 90.0%%\t%f\n", samples[num_samples * 9 / 10 - 1] * scale);
+ std::printf(" 99.0%%\t%f\n", samples[num_samples * 99 / 100 - 1] * scale);
+ std::printf(" 99.9%%\t%f\n", samples[num_samples * 999 / 1000 - 1] * scale);
+ std::printf("100.0%%\t%f\n", samples[num_samples - 1] * scale);
+
+ double total = 0.0;
+ for (int i = 0; i < num_samples; ++i) total += samples[i] * scale;
+ std::printf(" mean\t%f\n", total / num_samples);
+}
diff --git a/src/boost/libs/asio/test/latency/tcp_server.cpp b/src/boost/libs/asio/test/latency/tcp_server.cpp
new file mode 100644
index 000000000..587d774f0
--- /dev/null
+++ b/src/boost/libs/asio/test/latency/tcp_server.cpp
@@ -0,0 +1,114 @@
+//
+// tcp_server.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/shared_ptr.hpp>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+
+using boost::asio::ip::tcp;
+
+#include <boost/asio/yield.hpp>
+
+class tcp_server : boost::asio::coroutine
+{
+public:
+ tcp_server(tcp::acceptor& acceptor, std::size_t buf_size) :
+ acceptor_(acceptor),
+ socket_(acceptor_.get_executor()),
+ buffer_(buf_size)
+ {
+ }
+
+ void operator()(boost::system::error_code ec, std::size_t n = 0)
+ {
+ reenter (this) for (;;)
+ {
+ yield acceptor_.async_accept(socket_, ref(this));
+
+ while (!ec)
+ {
+ yield boost::asio::async_read(socket_,
+ boost::asio::buffer(buffer_), ref(this));
+
+ if (!ec)
+ {
+ for (std::size_t i = 0; i < n; ++i) buffer_[i] = ~buffer_[i];
+
+ yield boost::asio::async_write(socket_,
+ boost::asio::buffer(buffer_), ref(this));
+ }
+ }
+
+ socket_.close();
+ }
+ }
+
+ struct ref
+ {
+ explicit ref(tcp_server* p)
+ : p_(p)
+ {
+ }
+
+ void operator()(boost::system::error_code ec, std::size_t n = 0)
+ {
+ (*p_)(ec, n);
+ }
+
+ private:
+ tcp_server* p_;
+ };
+
+private:
+ tcp::acceptor& acceptor_;
+ tcp::socket socket_;
+ std::vector<unsigned char> buffer_;
+ tcp::endpoint sender_;
+};
+
+#include <boost/asio/unyield.hpp>
+
+int main(int argc, char* argv[])
+{
+ if (argc != 5)
+ {
+ std::fprintf(stderr,
+ "Usage: tcp_server <port> <nconns> "
+ "<bufsize> {spin|block}\n");
+ return 1;
+ }
+
+ unsigned short port = static_cast<unsigned short>(std::atoi(argv[1]));
+ int max_connections = std::atoi(argv[2]);
+ std::size_t buf_size = std::atoi(argv[3]);
+ bool spin = (std::strcmp(argv[4], "spin") == 0);
+
+ boost::asio::io_context io_context(1);
+ tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));
+ std::vector<boost::shared_ptr<tcp_server> > servers;
+
+ for (int i = 0; i < max_connections; ++i)
+ {
+ boost::shared_ptr<tcp_server> s(new tcp_server(acceptor, buf_size));
+ servers.push_back(s);
+ (*s)(boost::system::error_code());
+ }
+
+ if (spin)
+ for (;;) io_context.poll();
+ else
+ io_context.run();
+}
diff --git a/src/boost/libs/asio/test/latency/udp_client.cpp b/src/boost/libs/asio/test/latency/udp_client.cpp
new file mode 100644
index 000000000..e2ac4396d
--- /dev/null
+++ b/src/boost/libs/asio/test/latency/udp_client.cpp
@@ -0,0 +1,104 @@
+//
+// udp_client.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/ip/udp.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+#include "high_res_clock.hpp"
+
+using boost::asio::ip::udp;
+using boost::posix_time::ptime;
+using boost::posix_time::microsec_clock;
+
+const int num_samples = 100000;
+
+int main(int argc, char* argv[])
+{
+ if (argc != 6)
+ {
+ std::fprintf(stderr,
+ "Usage: udp_client <ip> <port1> "
+ "<nports> <bufsize> {spin|block}\n");
+ return 1;
+ }
+
+ const char* ip = argv[1];
+ unsigned short first_port = static_cast<unsigned short>(std::atoi(argv[2]));
+ unsigned short num_ports = static_cast<unsigned short>(std::atoi(argv[3]));
+ std::size_t buf_size = static_cast<std::size_t>(std::atoi(argv[4]));
+ bool spin = (std::strcmp(argv[5], "spin") == 0);
+
+ boost::asio::io_context io_context;
+
+ udp::socket socket(io_context, udp::endpoint(udp::v4(), 0));
+
+ if (spin)
+ {
+ socket.non_blocking(true);
+ }
+
+ udp::endpoint target(boost::asio::ip::make_address(ip), first_port);
+ unsigned short last_port = first_port + num_ports - 1;
+ std::vector<unsigned char> write_buf(buf_size);
+ std::vector<unsigned char> read_buf(buf_size);
+
+ ptime start = microsec_clock::universal_time();
+ boost::uint64_t start_hr = high_res_clock();
+
+ boost::uint64_t samples[num_samples];
+ for (int i = 0; i < num_samples; ++i)
+ {
+ boost::uint64_t t = high_res_clock();
+
+ boost::system::error_code ec;
+ socket.send_to(boost::asio::buffer(write_buf), target, 0, ec);
+
+ do socket.receive(boost::asio::buffer(read_buf), 0, ec);
+ while (ec == boost::asio::error::would_block);
+
+ samples[i] = high_res_clock() - t;
+
+ if (target.port() == last_port)
+ target.port(first_port);
+ else
+ target.port(target.port() + 1);
+ }
+
+ ptime stop = microsec_clock::universal_time();
+ boost::uint64_t stop_hr = high_res_clock();
+ boost::uint64_t elapsed_usec = (stop - start).total_microseconds();
+ boost::uint64_t elapsed_hr = stop_hr - start_hr;
+ double scale = 1.0 * elapsed_usec / elapsed_hr;
+
+ std::sort(samples, samples + num_samples);
+ std::printf(" 0.0%%\t%f\n", samples[0] * scale);
+ std::printf(" 0.1%%\t%f\n", samples[num_samples / 1000 - 1] * scale);
+ std::printf(" 1.0%%\t%f\n", samples[num_samples / 100 - 1] * scale);
+ std::printf(" 10.0%%\t%f\n", samples[num_samples / 10 - 1] * scale);
+ std::printf(" 20.0%%\t%f\n", samples[num_samples * 2 / 10 - 1] * scale);
+ std::printf(" 30.0%%\t%f\n", samples[num_samples * 3 / 10 - 1] * scale);
+ std::printf(" 40.0%%\t%f\n", samples[num_samples * 4 / 10 - 1] * scale);
+ std::printf(" 50.0%%\t%f\n", samples[num_samples * 5 / 10 - 1] * scale);
+ std::printf(" 60.0%%\t%f\n", samples[num_samples * 6 / 10 - 1] * scale);
+ std::printf(" 70.0%%\t%f\n", samples[num_samples * 7 / 10 - 1] * scale);
+ std::printf(" 80.0%%\t%f\n", samples[num_samples * 8 / 10 - 1] * scale);
+ std::printf(" 90.0%%\t%f\n", samples[num_samples * 9 / 10 - 1] * scale);
+ std::printf(" 99.0%%\t%f\n", samples[num_samples * 99 / 100 - 1] * scale);
+ std::printf(" 99.9%%\t%f\n", samples[num_samples * 999 / 1000 - 1] * scale);
+ std::printf("100.0%%\t%f\n", samples[num_samples - 1] * scale);
+
+ double total = 0.0;
+ for (int i = 0; i < num_samples; ++i) total += samples[i] * scale;
+ std::printf(" mean\t%f\n", total / num_samples);
+}
diff --git a/src/boost/libs/asio/test/latency/udp_server.cpp b/src/boost/libs/asio/test/latency/udp_server.cpp
new file mode 100644
index 000000000..4bba70059
--- /dev/null
+++ b/src/boost/libs/asio/test/latency/udp_server.cpp
@@ -0,0 +1,125 @@
+//
+// udp_server.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 <boost/asio/io_context.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/shared_ptr.hpp>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+#include "allocator.hpp"
+
+using boost::asio::ip::udp;
+
+#include <boost/asio/yield.hpp>
+
+class udp_server : boost::asio::coroutine
+{
+public:
+ udp_server(boost::asio::io_context& io_context,
+ unsigned short port, std::size_t buf_size) :
+ socket_(io_context, udp::endpoint(udp::v4(), port)),
+ buffer_(buf_size)
+ {
+ }
+
+ void operator()(boost::system::error_code ec, std::size_t n = 0)
+ {
+ reenter (this) for (;;)
+ {
+ yield socket_.async_receive_from(
+ boost::asio::buffer(buffer_),
+ sender_, ref(this));
+
+ if (!ec)
+ {
+ for (std::size_t i = 0; i < n; ++i) buffer_[i] = ~buffer_[i];
+ socket_.send_to(boost::asio::buffer(buffer_, n), sender_, 0, ec);
+ }
+ }
+ }
+
+ friend void* asio_handler_allocate(std::size_t n, udp_server* s)
+ {
+ return s->allocator_.allocate(n);
+ }
+
+ friend void asio_handler_deallocate(void* p, std::size_t, udp_server* s)
+ {
+ s->allocator_.deallocate(p);
+ }
+
+ struct ref
+ {
+ explicit ref(udp_server* p)
+ : p_(p)
+ {
+ }
+
+ void operator()(boost::system::error_code ec, std::size_t n = 0)
+ {
+ (*p_)(ec, n);
+ }
+
+ private:
+ udp_server* p_;
+
+ friend void* asio_handler_allocate(std::size_t n, ref* r)
+ {
+ return asio_handler_allocate(n, r->p_);
+ }
+
+ friend void asio_handler_deallocate(void* p, std::size_t n, ref* r)
+ {
+ asio_handler_deallocate(p, n, r->p_);
+ }
+ };
+
+private:
+ udp::socket socket_;
+ std::vector<unsigned char> buffer_;
+ udp::endpoint sender_;
+ allocator allocator_;
+};
+
+#include <boost/asio/unyield.hpp>
+
+int main(int argc, char* argv[])
+{
+ if (argc != 5)
+ {
+ std::fprintf(stderr,
+ "Usage: udp_server <port1> <nports> "
+ "<bufsize> {spin|block}\n");
+ return 1;
+ }
+
+ unsigned short first_port = static_cast<unsigned short>(std::atoi(argv[1]));
+ unsigned short num_ports = static_cast<unsigned short>(std::atoi(argv[2]));
+ std::size_t buf_size = std::atoi(argv[3]);
+ bool spin = (std::strcmp(argv[4], "spin") == 0);
+
+ boost::asio::io_context io_context(1);
+ std::vector<boost::shared_ptr<udp_server> > servers;
+
+ for (unsigned short i = 0; i < num_ports; ++i)
+ {
+ unsigned short port = first_port + i;
+ boost::shared_ptr<udp_server> s(new udp_server(io_context, port, buf_size));
+ servers.push_back(s);
+ (*s)(boost::system::error_code());
+ }
+
+ if (spin)
+ for (;;) io_context.poll();
+ else
+ io_context.run();
+}
diff --git a/src/boost/libs/asio/test/local/basic_endpoint.cpp b/src/boost/libs/asio/test/local/basic_endpoint.cpp
new file mode 100644
index 000000000..15ed7cedd
--- /dev/null
+++ b/src/boost/libs/asio/test/local/basic_endpoint.cpp
@@ -0,0 +1,25 @@
+//
+// basic_endpoint.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/local/basic_endpoint.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "local/basic_endpoint",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/local/connect_pair.cpp b/src/boost/libs/asio/test/local/connect_pair.cpp
new file mode 100644
index 000000000..a2faad90c
--- /dev/null
+++ b/src/boost/libs/asio/test/local/connect_pair.cpp
@@ -0,0 +1,76 @@
+//
+// connect_pair.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/local/connect_pair.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/local/datagram_protocol.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// local_connect_pair_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all host_name functions compile and link
+// correctly. Runtime failures are ignored.
+
+namespace local_connect_pair_compile {
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ using namespace boost::asio;
+ namespace local = boost::asio::local;
+ typedef local::datagram_protocol dp;
+ typedef local::stream_protocol sp;
+
+ try
+ {
+ boost::asio::io_context io_context;
+ boost::system::error_code ec1;
+
+ dp::socket s1(io_context);
+ dp::socket s2(io_context);
+ local::connect_pair(s1, s2);
+
+ dp::socket s3(io_context);
+ dp::socket s4(io_context);
+ local::connect_pair(s3, s4, ec1);
+
+ sp::socket s5(io_context);
+ sp::socket s6(io_context);
+ local::connect_pair(s5, s6);
+
+ sp::socket s7(io_context);
+ sp::socket s8(io_context);
+ local::connect_pair(s7, s8, ec1);
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+}
+
+} // namespace local_connect_pair_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "local/connect_pair",
+ BOOST_ASIO_TEST_CASE(local_connect_pair_compile::test)
+)
diff --git a/src/boost/libs/asio/test/local/datagram_protocol.cpp b/src/boost/libs/asio/test/local/datagram_protocol.cpp
new file mode 100644
index 000000000..d85e09ec7
--- /dev/null
+++ b/src/boost/libs/asio/test/local/datagram_protocol.cpp
@@ -0,0 +1,242 @@
+//
+// datagram_protocol.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/local/datagram_protocol.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// local_datagram_protocol_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// local::datagram_socket::socket compile and link correctly. Runtime failures
+// are ignored.
+
+namespace local_datagram_protocol_socket_compile {
+
+void connect_handler(const boost::system::error_code&)
+{
+}
+
+void send_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void receive_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ using namespace boost::asio;
+ namespace local = boost::asio::local;
+ typedef local::datagram_protocol dp;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ socket_base::message_flags in_flags = 0;
+ socket_base::send_buffer_size socket_option;
+ socket_base::bytes_readable io_control_command;
+ boost::system::error_code ec;
+
+ // basic_datagram_socket constructors.
+
+ dp::socket socket1(ioc);
+ dp::socket socket2(ioc, dp());
+ dp::socket socket3(ioc, dp::endpoint(""));
+ int native_socket1 = ::socket(AF_UNIX, SOCK_DGRAM, 0);
+ dp::socket socket4(ioc, dp(), native_socket1);
+
+ dp::socket socket5(ioc_ex);
+ dp::socket socket6(ioc_ex, dp());
+ dp::socket socket7(ioc_ex, dp::endpoint(""));
+ int native_socket2 = ::socket(AF_UNIX, SOCK_DGRAM, 0);
+ dp::socket socket8(ioc_ex, dp(), native_socket2);
+
+ // basic_io_object functions.
+
+ dp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ dp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ socket1.open(dp());
+ socket1.open(dp(), ec);
+
+ int native_socket3 = ::socket(AF_UNIX, SOCK_DGRAM, 0);
+ socket1.assign(dp(), native_socket3);
+ int native_socket4 = ::socket(AF_UNIX, SOCK_DGRAM, 0);
+ socket1.assign(dp(), native_socket4, ec);
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ dp::socket::native_handle_type native_socket5 = socket1.native_handle();
+ (void)native_socket5;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(dp::endpoint(""));
+ socket1.bind(dp::endpoint(""), ec);
+
+ socket1.connect(dp::endpoint(""));
+ socket1.connect(dp::endpoint(""), ec);
+
+ socket1.async_connect(dp::endpoint(""), connect_handler);
+
+ socket1.set_option(socket_option);
+ socket1.set_option(socket_option, ec);
+
+ socket1.get_option(socket_option);
+ socket1.get_option(socket_option, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ dp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ dp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ dp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ dp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ // basic_datagram_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer));
+ socket1.send(buffer(const_char_buffer));
+ socket1.send(null_buffers());
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), send_handler);
+ socket1.async_send(buffer(const_char_buffer), send_handler);
+ socket1.async_send(null_buffers(), send_handler);
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler);
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler);
+ socket1.async_send(null_buffers(), in_flags, send_handler);
+
+ socket1.send_to(buffer(mutable_char_buffer),
+ dp::endpoint(""));
+ socket1.send_to(buffer(const_char_buffer),
+ dp::endpoint(""));
+ socket1.send_to(null_buffers(),
+ dp::endpoint(""));
+ socket1.send_to(buffer(mutable_char_buffer),
+ dp::endpoint(""), in_flags);
+ socket1.send_to(buffer(const_char_buffer),
+ dp::endpoint(""), in_flags);
+ socket1.send_to(null_buffers(),
+ dp::endpoint(""), in_flags);
+ socket1.send_to(buffer(mutable_char_buffer),
+ dp::endpoint(""), in_flags, ec);
+ socket1.send_to(buffer(const_char_buffer),
+ dp::endpoint(""), in_flags, ec);
+ socket1.send_to(null_buffers(),
+ dp::endpoint(""), in_flags, ec);
+
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ dp::endpoint(""), send_handler);
+ socket1.async_send_to(buffer(const_char_buffer),
+ dp::endpoint(""), send_handler);
+ socket1.async_send_to(null_buffers(),
+ dp::endpoint(""), send_handler);
+ socket1.async_send_to(buffer(mutable_char_buffer),
+ dp::endpoint(""), in_flags, send_handler);
+ socket1.async_send_to(buffer(const_char_buffer),
+ dp::endpoint(""), in_flags, send_handler);
+ socket1.async_send_to(null_buffers(),
+ dp::endpoint(""), in_flags, send_handler);
+
+ socket1.receive(buffer(mutable_char_buffer));
+ socket1.receive(null_buffers());
+ socket1.receive(buffer(mutable_char_buffer), in_flags);
+ socket1.receive(null_buffers(), in_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.receive(null_buffers(), in_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), receive_handler);
+ socket1.async_receive(null_buffers(), receive_handler);
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ receive_handler);
+ socket1.async_receive(null_buffers(), in_flags, receive_handler);
+
+ dp::endpoint endpoint;
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint);
+ socket1.receive_from(null_buffers(), endpoint);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags);
+ socket1.receive_from(null_buffers(), endpoint, in_flags);
+ socket1.receive_from(buffer(mutable_char_buffer), endpoint, in_flags, ec);
+ socket1.receive_from(null_buffers(), endpoint, in_flags, ec);
+
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, receive_handler);
+ socket1.async_receive_from(null_buffers(),
+ endpoint, receive_handler);
+ socket1.async_receive_from(buffer(mutable_char_buffer),
+ endpoint, in_flags, receive_handler);
+ socket1.async_receive_from(null_buffers(),
+ endpoint, in_flags, receive_handler);
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+}
+
+} // namespace local_datagram_protocol_socket_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "local/datagram_protocol",
+ BOOST_ASIO_TEST_CASE(local_datagram_protocol_socket_compile::test)
+)
diff --git a/src/boost/libs/asio/test/local/stream_protocol.cpp b/src/boost/libs/asio/test/local/stream_protocol.cpp
new file mode 100644
index 000000000..6728393c0
--- /dev/null
+++ b/src/boost/libs/asio/test/local/stream_protocol.cpp
@@ -0,0 +1,219 @@
+//
+// stream_protocol.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/local/stream_protocol.hpp>
+
+#include <cstring>
+#include <boost/asio/io_context.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// local_stream_protocol_socket_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// local::stream_protocol::socket compile and link correctly. Runtime failures
+// are ignored.
+
+namespace local_stream_protocol_socket_compile {
+
+void connect_handler(const boost::system::error_code&)
+{
+}
+
+void send_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void receive_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ using namespace boost::asio;
+ namespace local = boost::asio::local;
+ typedef local::stream_protocol sp;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ socket_base::message_flags in_flags = 0;
+ socket_base::keep_alive socket_option;
+ socket_base::bytes_readable io_control_command;
+ boost::system::error_code ec;
+
+ // basic_stream_socket constructors.
+
+ sp::socket socket1(ioc);
+ sp::socket socket2(ioc, sp());
+ sp::socket socket3(ioc, sp::endpoint(""));
+ int native_socket1 = ::socket(AF_UNIX, SOCK_STREAM, 0);
+ sp::socket socket4(ioc, sp(), native_socket1);
+
+ sp::socket socket5(ioc_ex);
+ sp::socket socket6(ioc_ex, sp());
+ sp::socket socket7(ioc_ex, sp::endpoint(""));
+ int native_socket2 = ::socket(AF_UNIX, SOCK_STREAM, 0);
+ sp::socket socket8(ioc_ex, sp(), native_socket2);
+
+ // basic_io_object functions.
+
+ sp::socket::executor_type ex = socket1.get_executor();
+ (void)ex;
+
+ // basic_socket functions.
+
+ sp::socket::lowest_layer_type& lowest_layer = socket1.lowest_layer();
+ (void)lowest_layer;
+
+ socket1.open(sp());
+ socket1.open(sp(), ec);
+
+ int native_socket3 = ::socket(AF_UNIX, SOCK_STREAM, 0);
+ socket1.assign(sp(), native_socket3);
+ int native_socket4 = ::socket(AF_UNIX, SOCK_STREAM, 0);
+ socket1.assign(sp(), native_socket4, ec);
+
+ bool is_open = socket1.is_open();
+ (void)is_open;
+
+ socket1.close();
+ socket1.close(ec);
+
+ sp::socket::native_handle_type native_socket5 = socket1.native_handle();
+ (void)native_socket5;
+
+ socket1.cancel();
+ socket1.cancel(ec);
+
+ bool at_mark1 = socket1.at_mark();
+ (void)at_mark1;
+ bool at_mark2 = socket1.at_mark(ec);
+ (void)at_mark2;
+
+ std::size_t available1 = socket1.available();
+ (void)available1;
+ std::size_t available2 = socket1.available(ec);
+ (void)available2;
+
+ socket1.bind(sp::endpoint(""));
+ socket1.bind(sp::endpoint(""), ec);
+
+ socket1.connect(sp::endpoint(""));
+ socket1.connect(sp::endpoint(""), ec);
+
+ socket1.async_connect(sp::endpoint(""), connect_handler);
+
+ socket1.set_option(socket_option);
+ socket1.set_option(socket_option, ec);
+
+ socket1.get_option(socket_option);
+ socket1.get_option(socket_option, ec);
+
+ socket1.io_control(io_control_command);
+ socket1.io_control(io_control_command, ec);
+
+ sp::endpoint endpoint1 = socket1.local_endpoint();
+ (void)endpoint1;
+ sp::endpoint endpoint2 = socket1.local_endpoint(ec);
+ (void)endpoint2;
+
+ sp::endpoint endpoint3 = socket1.remote_endpoint();
+ (void)endpoint3;
+ sp::endpoint endpoint4 = socket1.remote_endpoint(ec);
+ (void)endpoint4;
+
+ socket1.shutdown(socket_base::shutdown_both);
+ socket1.shutdown(socket_base::shutdown_both, ec);
+
+ // basic_stream_socket functions.
+
+ socket1.send(buffer(mutable_char_buffer));
+ socket1.send(buffer(const_char_buffer));
+ socket1.send(null_buffers());
+ socket1.send(buffer(mutable_char_buffer), in_flags);
+ socket1.send(buffer(const_char_buffer), in_flags);
+ socket1.send(null_buffers(), in_flags);
+ socket1.send(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.send(buffer(const_char_buffer), in_flags, ec);
+ socket1.send(null_buffers(), in_flags, ec);
+
+ socket1.async_send(buffer(mutable_char_buffer), send_handler);
+ socket1.async_send(buffer(const_char_buffer), send_handler);
+ socket1.async_send(null_buffers(), send_handler);
+ socket1.async_send(buffer(mutable_char_buffer), in_flags, send_handler);
+ socket1.async_send(buffer(const_char_buffer), in_flags, send_handler);
+ socket1.async_send(null_buffers(), in_flags, send_handler);
+
+ socket1.receive(buffer(mutable_char_buffer));
+ socket1.receive(null_buffers());
+ socket1.receive(buffer(mutable_char_buffer), in_flags);
+ socket1.receive(null_buffers(), in_flags);
+ socket1.receive(buffer(mutable_char_buffer), in_flags, ec);
+ socket1.receive(null_buffers(), in_flags, ec);
+
+ socket1.async_receive(buffer(mutable_char_buffer), receive_handler);
+ socket1.async_receive(null_buffers(), receive_handler);
+ socket1.async_receive(buffer(mutable_char_buffer), in_flags,
+ receive_handler);
+ socket1.async_receive(null_buffers(), in_flags, receive_handler);
+
+ socket1.write_some(buffer(mutable_char_buffer));
+ socket1.write_some(buffer(const_char_buffer));
+ socket1.write_some(null_buffers());
+ socket1.write_some(buffer(mutable_char_buffer), ec);
+ socket1.write_some(buffer(const_char_buffer), ec);
+ socket1.write_some(null_buffers(), ec);
+
+ socket1.async_write_some(buffer(mutable_char_buffer), write_some_handler);
+ socket1.async_write_some(buffer(const_char_buffer), write_some_handler);
+ socket1.async_write_some(null_buffers(), write_some_handler);
+
+ socket1.read_some(buffer(mutable_char_buffer));
+ socket1.read_some(buffer(mutable_char_buffer), ec);
+ socket1.read_some(null_buffers(), ec);
+
+ socket1.async_read_some(buffer(mutable_char_buffer), read_some_handler);
+ socket1.async_read_some(null_buffers(), read_some_handler);
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+}
+
+} // namespace local_stream_protocol_socket_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "local/stream_protocol",
+ BOOST_ASIO_TEST_CASE(local_stream_protocol_socket_compile::test)
+)
diff --git a/src/boost/libs/asio/test/packaged_task.cpp b/src/boost/libs/asio/test/packaged_task.cpp
new file mode 100644
index 000000000..ba6494aed
--- /dev/null
+++ b/src/boost/libs/asio/test/packaged_task.cpp
@@ -0,0 +1,25 @@
+//
+// packaged_task.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/packaged_task.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "packaged_task",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/placeholders.cpp b/src/boost/libs/asio/test/placeholders.cpp
new file mode 100644
index 000000000..7524929da
--- /dev/null
+++ b/src/boost/libs/asio/test/placeholders.cpp
@@ -0,0 +1,25 @@
+//
+// placeholders.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/placeholders.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "placeholders",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/posix/basic_descriptor.cpp b/src/boost/libs/asio/test/posix/basic_descriptor.cpp
new file mode 100644
index 000000000..ffde113eb
--- /dev/null
+++ b/src/boost/libs/asio/test/posix/basic_descriptor.cpp
@@ -0,0 +1,25 @@
+//
+// basic_descriptor.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/posix/basic_descriptor.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "posix/basic_descriptor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/posix/basic_stream_descriptor.cpp b/src/boost/libs/asio/test/posix/basic_stream_descriptor.cpp
new file mode 100644
index 000000000..55581a849
--- /dev/null
+++ b/src/boost/libs/asio/test/posix/basic_stream_descriptor.cpp
@@ -0,0 +1,25 @@
+//
+// basic_stream_descriptor.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/posix/basic_stream_descriptor.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "posix/basic_stream_descriptor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/posix/descriptor.cpp b/src/boost/libs/asio/test/posix/descriptor.cpp
new file mode 100644
index 000000000..76fa56f7d
--- /dev/null
+++ b/src/boost/libs/asio/test/posix/descriptor.cpp
@@ -0,0 +1,25 @@
+//
+// descriptor.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/posix/descriptor.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "posix/descriptor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/posix/descriptor_base.cpp b/src/boost/libs/asio/test/posix/descriptor_base.cpp
new file mode 100644
index 000000000..5e1cfa597
--- /dev/null
+++ b/src/boost/libs/asio/test/posix/descriptor_base.cpp
@@ -0,0 +1,25 @@
+//
+// descriptor_base.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/posix/descriptor_base.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "posix/descriptor_base",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/posix/stream_descriptor.cpp b/src/boost/libs/asio/test/posix/stream_descriptor.cpp
new file mode 100644
index 000000000..4d0b9c84f
--- /dev/null
+++ b/src/boost/libs/asio/test/posix/stream_descriptor.cpp
@@ -0,0 +1,183 @@
+//
+// stream_descriptor.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/posix/stream_descriptor.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include "../archetypes/async_result.hpp"
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// posix_stream_descriptor_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// posix::stream_descriptor compile and link correctly. Runtime failures are
+// ignored.
+
+namespace posix_stream_descriptor_compile {
+
+void wait_handler(const boost::system::error_code&)
+{
+}
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+ using namespace boost::asio;
+ namespace posix = boost::asio::posix;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ posix::descriptor_base::bytes_readable io_control_command;
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_stream_descriptor constructors.
+
+ posix::stream_descriptor descriptor1(ioc);
+ posix::stream_descriptor descriptor2(ioc_ex);
+ int native_descriptor1 = -1;
+ posix::stream_descriptor descriptor3(ioc, native_descriptor1);
+ posix::stream_descriptor descriptor4(ioc_ex, native_descriptor1);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ posix::stream_descriptor descriptor5(std::move(descriptor2));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_stream_descriptor operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ descriptor1 = posix::stream_descriptor(ioc);
+ descriptor1 = std::move(descriptor2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ posix::stream_descriptor::executor_type ex = descriptor1.get_executor();
+ (void)ex;
+
+ // basic_descriptor functions.
+
+ posix::stream_descriptor::lowest_layer_type& lowest_layer
+ = descriptor1.lowest_layer();
+ (void)lowest_layer;
+
+ const posix::stream_descriptor& descriptor6 = descriptor1;
+ const posix::stream_descriptor::lowest_layer_type& lowest_layer2
+ = descriptor6.lowest_layer();
+ (void)lowest_layer2;
+
+ int native_descriptor2 = -1;
+ descriptor1.assign(native_descriptor2);
+
+ bool is_open = descriptor1.is_open();
+ (void)is_open;
+
+ descriptor1.close();
+ descriptor1.close(ec);
+
+ posix::stream_descriptor::native_handle_type native_descriptor3
+ = descriptor1.native_handle();
+ (void)native_descriptor3;
+
+ posix::stream_descriptor::native_handle_type native_descriptor4
+ = descriptor1.release();
+ (void)native_descriptor4;
+
+ descriptor1.cancel();
+ descriptor1.cancel(ec);
+
+ descriptor1.io_control(io_control_command);
+ descriptor1.io_control(io_control_command, ec);
+
+ bool non_blocking1 = descriptor1.non_blocking();
+ (void)non_blocking1;
+ descriptor1.non_blocking(true);
+ descriptor1.non_blocking(false, ec);
+
+ bool non_blocking2 = descriptor1.native_non_blocking();
+ (void)non_blocking2;
+ descriptor1.native_non_blocking(true);
+ descriptor1.native_non_blocking(false, ec);
+
+ descriptor1.wait(posix::descriptor_base::wait_read);
+ descriptor1.wait(posix::descriptor_base::wait_write, ec);
+
+ descriptor1.async_wait(posix::descriptor_base::wait_read, &wait_handler);
+ int i1 = descriptor1.async_wait(posix::descriptor_base::wait_write, lazy);
+ (void)i1;
+
+ // basic_stream_descriptor functions.
+
+ descriptor1.write_some(buffer(mutable_char_buffer));
+ descriptor1.write_some(buffer(const_char_buffer));
+ descriptor1.write_some(null_buffers());
+ descriptor1.write_some(buffer(mutable_char_buffer), ec);
+ descriptor1.write_some(buffer(const_char_buffer), ec);
+ descriptor1.write_some(null_buffers(), ec);
+
+ descriptor1.async_write_some(buffer(mutable_char_buffer),
+ write_some_handler);
+ descriptor1.async_write_some(buffer(const_char_buffer),
+ write_some_handler);
+ descriptor1.async_write_some(null_buffers(),
+ write_some_handler);
+ int i2 = descriptor1.async_write_some(buffer(mutable_char_buffer), lazy);
+ (void)i2;
+ int i3 = descriptor1.async_write_some(buffer(const_char_buffer), lazy);
+ (void)i3;
+ int i4 = descriptor1.async_write_some(null_buffers(), lazy);
+ (void)i4;
+
+ descriptor1.read_some(buffer(mutable_char_buffer));
+ descriptor1.read_some(buffer(mutable_char_buffer), ec);
+ descriptor1.read_some(null_buffers(), ec);
+
+ descriptor1.async_read_some(buffer(mutable_char_buffer), read_some_handler);
+ descriptor1.async_read_some(null_buffers(), read_some_handler);
+ int i5 = descriptor1.async_read_some(buffer(mutable_char_buffer), lazy);
+ (void)i5;
+ int i6 = descriptor1.async_read_some(null_buffers(), lazy);
+ (void)i6;
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+}
+
+} // namespace posix_stream_descriptor_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "posix/stream_descriptor",
+ BOOST_ASIO_TEST_CASE(posix_stream_descriptor_compile::test)
+)
diff --git a/src/boost/libs/asio/test/post.cpp b/src/boost/libs/asio/test/post.cpp
new file mode 100644
index 000000000..f02680b45
--- /dev/null
+++ b/src/boost/libs/asio/test/post.cpp
@@ -0,0 +1,25 @@
+//
+// post.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/post.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "post",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/read.cpp b/src/boost/libs/asio/test/read.cpp
new file mode 100644
index 000000000..bd099c1c2
--- /dev/null
+++ b/src/boost/libs/asio/test/read.cpp
@@ -0,0 +1,4997 @@
+//
+// read.cpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/read.hpp>
+
+#include <cstring>
+#include <vector>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/streambuf.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+#include <boost/array.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+using namespace std; // For memcmp, memcpy and memset.
+
+class test_stream
+{
+public:
+ typedef boost::asio::io_context::executor_type executor_type;
+
+ test_stream(boost::asio::io_context& io_context)
+ : io_context_(io_context),
+ length_(0),
+ position_(0),
+ next_read_length_(0)
+ {
+ }
+
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return io_context_.get_executor();
+ }
+
+ void reset(const void* data, size_t length)
+ {
+ BOOST_ASIO_CHECK(length <= max_length);
+
+ memcpy(data_, data, length);
+ length_ = length;
+ position_ = 0;
+ next_read_length_ = length;
+ }
+
+ void next_read_length(size_t length)
+ {
+ next_read_length_ = length;
+ }
+
+ template <typename Iterator>
+ bool check_buffers(Iterator begin, Iterator end, size_t length)
+ {
+ if (length != position_)
+ return false;
+
+ Iterator iter = begin;
+ size_t checked_length = 0;
+ for (; iter != end && checked_length < length; ++iter)
+ {
+ size_t buffer_length = boost::asio::buffer_size(*iter);
+ if (buffer_length > length - checked_length)
+ buffer_length = length - checked_length;
+ if (memcmp(data_ + checked_length, iter->data(), buffer_length) != 0)
+ return false;
+ checked_length += buffer_length;
+ }
+
+ return true;
+ }
+
+ template <typename Const_Buffers>
+ bool check_buffers(const Const_Buffers& buffers, size_t length)
+ {
+ return check_buffers(boost::asio::buffer_sequence_begin(buffers),
+ boost::asio::buffer_sequence_end(buffers), length);
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read_some(const Mutable_Buffers& buffers)
+ {
+ size_t n = boost::asio::buffer_copy(buffers,
+ boost::asio::buffer(data_, length_) + position_,
+ next_read_length_);
+ position_ += n;
+ return n;
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read_some(const Mutable_Buffers& buffers,
+ boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return read_some(buffers);
+ }
+
+ template <typename Mutable_Buffers, typename Handler>
+ void async_read_some(const Mutable_Buffers& buffers,
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ {
+ size_t bytes_transferred = read_some(buffers);
+ boost::asio::post(get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(Handler)(handler),
+ boost::system::error_code(), bytes_transferred));
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ enum { max_length = 8192 };
+ char data_[max_length];
+ size_t length_;
+ size_t position_;
+ size_t next_read_length_;
+};
+
+static const char read_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void test_2_arg_zero_buffers_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::mutable_buffer> buffers;
+
+ size_t bytes_transferred = boost::asio::read(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void test_2_arg_mutable_buffer_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ size_t bytes_transferred = boost::asio::read(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+}
+
+void test_2_arg_vector_buffers_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf, 39) + 32);
+ buffers.push_back(boost::asio::buffer(read_buf) + 39);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ size_t bytes_transferred = boost::asio::read(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+}
+
+void test_2_arg_dynamic_string_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ size_t bytes_transferred = boost::asio::read(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+}
+
+void test_2_arg_streambuf_read()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ size_t bytes_transferred = boost::asio::read(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void test_3_arg_nothrow_zero_buffers_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::mutable_buffer> buffers;
+
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_3_arg_nothrow_mutable_buffer_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_3_arg_nothrow_vector_buffers_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf, 39) + 32);
+ buffers.push_back(boost::asio::buffer(read_buf) + 39);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_3_arg_nothrow_dynamic_string_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_3_arg_nothrow_streambuf_read()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+bool old_style_transfer_all(const boost::system::error_code& ec,
+ size_t /*bytes_transferred*/)
+{
+ return !!ec;
+}
+
+struct short_transfer
+{
+ short_transfer() {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ short_transfer(short_transfer&&) {}
+#else // defined(BOOST_ASIO_HAS_MOVE)
+ short_transfer(const short_transfer&) {}
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+ size_t operator()(const boost::system::error_code& ec,
+ size_t /*bytes_transferred*/)
+ {
+ return !!ec ? 0 : 3;
+ }
+};
+
+void test_3_arg_mutable_buffer_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ size_t bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+}
+
+void test_3_arg_vector_buffers_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf, 39) + 32);
+ buffers.push_back(boost::asio::buffer(read_buf) + 39);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ size_t bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+}
+
+void test_3_arg_dynamic_string_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ size_t bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 50));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+}
+
+void test_3_arg_streambuf_read()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ size_t bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 50));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void test_4_arg_mutable_buffer_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_vector_buffers_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf, 39) + 32);
+ buffers.push_back(boost::asio::buffer(read_buf) + 39);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_dynamic_string_read()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_streambuf_read()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void async_read_handler(const boost::system::error_code& e,
+ size_t bytes_transferred, size_t expected_bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(!e);
+ BOOST_ASIO_CHECK(bytes_transferred == expected_bytes_transferred);
+}
+
+void test_3_arg_mutable_buffer_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+}
+
+void test_3_arg_boost_array_buffers_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+ boost::asio::buffer(read_buf, 32),
+ boost::asio::buffer(read_buf) + 32 } };
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+}
+
+void test_3_arg_std_array_buffers_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::array<boost::asio::mutable_buffer, 2> buffers = { {
+ boost::asio::buffer(read_buf, 32),
+ boost::asio::buffer(read_buf) + 32 } };
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+}
+
+void test_3_arg_vector_buffers_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf, 39) + 32);
+ buffers.push_back(boost::asio::buffer(read_buf) + 39);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+}
+
+void test_3_arg_dynamic_string_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bool called = false;
+ boost::asio::async_read(s, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ int i = boost::asio::async_read(s, sb, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+}
+
+void test_3_arg_streambuf_async_read()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bool called = false;
+ boost::asio::async_read(s, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ int i = boost::asio::async_read(s, sb, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void test_4_arg_mutable_buffer_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read(s, buffers,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+}
+
+void test_4_arg_boost_array_buffers_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+ boost::asio::buffer(read_buf, 32),
+ boost::asio::buffer(read_buf) + 32 } };
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read(s, buffers,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+}
+
+void test_4_arg_std_array_buffers_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::array<boost::asio::mutable_buffer, 2> buffers = { {
+ boost::asio::buffer(read_buf, 32),
+ boost::asio::buffer(read_buf) + 32 } };
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read(s, buffers,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+}
+
+void test_4_arg_vector_buffers_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf, 39) + 32);
+ buffers.push_back(boost::asio::buffer(read_buf) + 39);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read(s, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read(s, buffers,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(read_data)));
+}
+
+void test_4_arg_dynamic_string_async_read()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bool called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 50));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ int i = boost::asio::async_read(s, sb,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(0, sb.size()), sizeof(read_data)));
+}
+
+void test_4_arg_streambuf_async_read()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bool called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 50));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read(s, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ int i = boost::asio::async_read(s, sb,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(sb.data(), sizeof(read_data)));
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "read",
+ BOOST_ASIO_TEST_CASE(test_2_arg_zero_buffers_read)
+ BOOST_ASIO_TEST_CASE(test_2_arg_mutable_buffer_read)
+ BOOST_ASIO_TEST_CASE(test_2_arg_vector_buffers_read)
+ BOOST_ASIO_TEST_CASE(test_2_arg_dynamic_string_read)
+ BOOST_ASIO_TEST_CASE(test_2_arg_streambuf_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_zero_buffers_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_mutable_buffer_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_vector_buffers_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_dynamic_string_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_streambuf_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_mutable_buffer_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_vector_buffers_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_dynamic_string_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_streambuf_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_mutable_buffer_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_vector_buffers_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_dynamic_string_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_streambuf_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_mutable_buffer_async_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_boost_array_buffers_async_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_std_array_buffers_async_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_vector_buffers_async_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_dynamic_string_async_read)
+ BOOST_ASIO_TEST_CASE(test_3_arg_streambuf_async_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_mutable_buffer_async_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_vector_buffers_async_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_boost_array_buffers_async_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_std_array_buffers_async_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_dynamic_string_async_read)
+ BOOST_ASIO_TEST_CASE(test_4_arg_streambuf_async_read)
+)
diff --git a/src/boost/libs/asio/test/read_at.cpp b/src/boost/libs/asio/test/read_at.cpp
new file mode 100644
index 000000000..2d8abe239
--- /dev/null
+++ b/src/boost/libs/asio/test/read_at.cpp
@@ -0,0 +1,7502 @@
+//
+// read_at.cpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/read_at.hpp>
+
+#include <cstring>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/streambuf.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+#include <boost/array.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+using namespace std; // For memcmp, memcpy and memset.
+
+class test_random_access_device
+{
+public:
+ typedef boost::asio::io_context::executor_type executor_type;
+
+ test_random_access_device(boost::asio::io_context& io_context)
+ : io_context_(io_context),
+ length_(0),
+ next_read_length_(0)
+ {
+ }
+
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return io_context_.get_executor();
+ }
+
+ void reset(const void* data, size_t length)
+ {
+ BOOST_ASIO_CHECK(length <= max_length);
+
+ length_ = 0;
+ while (length_ + length < max_length)
+ {
+ memcpy(data_ + length_, data, length);
+ length_ += length;
+ }
+
+ next_read_length_ = length;
+ }
+
+ void next_read_length(size_t length)
+ {
+ next_read_length_ = length;
+ }
+
+ template <typename Iterator>
+ bool check_buffers(boost::asio::uint64_t offset,
+ Iterator begin, Iterator end, size_t length)
+ {
+ if (offset + length > max_length)
+ return false;
+
+ Iterator iter = begin;
+ size_t checked_length = 0;
+ for (; iter != end && checked_length < length; ++iter)
+ {
+ size_t buffer_length = boost::asio::buffer_size(*iter);
+ if (buffer_length > length - checked_length)
+ buffer_length = length - checked_length;
+ if (memcmp(data_ + offset + checked_length,
+ iter->data(), buffer_length) != 0)
+ return false;
+ checked_length += buffer_length;
+ }
+
+ return true;
+ }
+
+ template <typename Const_Buffers>
+ bool check_buffers(boost::asio::uint64_t offset,
+ const Const_Buffers& buffers, size_t length)
+ {
+ return check_buffers(offset, boost::asio::buffer_sequence_begin(buffers),
+ boost::asio::buffer_sequence_end(buffers), length);
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read_some_at(boost::asio::uint64_t offset,
+ const Mutable_Buffers& buffers)
+ {
+ return boost::asio::buffer_copy(buffers,
+ boost::asio::buffer(data_, length_) + offset,
+ next_read_length_);
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read_some_at(boost::asio::uint64_t offset,
+ const Mutable_Buffers& buffers, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return read_some_at(offset, buffers);
+ }
+
+ template <typename Mutable_Buffers, typename Handler>
+ void async_read_some_at(boost::asio::uint64_t offset,
+ const Mutable_Buffers& buffers, BOOST_ASIO_MOVE_ARG(Handler) handler)
+ {
+ size_t bytes_transferred = read_some_at(offset, buffers);
+ boost::asio::post(get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(Handler)(handler),
+ boost::system::error_code(), bytes_transferred));
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ enum { max_length = 8192 };
+ char data_[max_length];
+ size_t length_;
+ size_t next_read_length_;
+};
+
+static const char read_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void test_3_arg_mutable_buffer_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ size_t bytes_transferred = boost::asio::read_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+}
+
+void test_3_arg_vector_buffers_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf) + 32);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ size_t bytes_transferred = boost::asio::read_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+}
+
+void test_3_arg_streambuf_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ size_t bytes_transferred = boost::asio::read_at(s, 0, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+}
+
+void test_4_arg_nothrow_mutable_buffer_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_nothrow_vector_buffers_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf) + 32);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_nothrow_streambuf_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read_at(s, 0, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+bool old_style_transfer_all(const boost::system::error_code& ec,
+ size_t /*bytes_transferred*/)
+{
+ return !!ec;
+}
+
+struct short_transfer
+{
+ short_transfer() {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ short_transfer(short_transfer&&) {}
+#else // defined(BOOST_ASIO_HAS_MOVE)
+ short_transfer(const short_transfer&) {}
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+ size_t operator()(const boost::system::error_code& ec,
+ size_t /*bytes_transferred*/)
+ {
+ return !!ec ? 0 : 3;
+ }
+};
+
+void test_4_arg_mutable_buffer_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ size_t bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+}
+
+void test_4_arg_vector_buffers_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf) + 32);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ size_t bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+}
+
+void test_4_arg_streambuf_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ size_t bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 50));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 50));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+}
+
+void test_5_arg_mutable_buffer_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_5_arg_vector_buffers_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf) + 32);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_5_arg_streambuf_read_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 0, sb,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::read_at(s, 1234, sb,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(read_data));
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void async_read_handler(const boost::system::error_code& e,
+ size_t bytes_transferred, size_t expected_bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(!e);
+ BOOST_ASIO_CHECK(bytes_transferred == expected_bytes_transferred);
+}
+
+void test_4_arg_mutable_buffer_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read_at(s, 1234, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+}
+
+void test_4_arg_boost_array_buffers_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+ boost::asio::buffer(read_buf, 32),
+ boost::asio::buffer(read_buf) + 32 } };
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read_at(s, 1234, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+}
+
+void test_4_arg_std_array_buffers_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::array<boost::asio::mutable_buffer, 2> buffers = { {
+ boost::asio::buffer(read_buf, 32),
+ boost::asio::buffer(read_buf) + 32 } };
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read_at(s, 1234, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+}
+
+void test_4_arg_vector_buffers_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf) + 32);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read_at(s, 1234, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+}
+
+void test_4_arg_streambuf_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bool called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ int i = boost::asio::async_read_at(s, 1234, sb,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+}
+
+void test_5_arg_mutable_buffer_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read_at(s, 1234, buffers,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+}
+
+void test_5_arg_boost_array_buffers_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+ boost::asio::buffer(read_buf, 32),
+ boost::asio::buffer(read_buf) + 32 } };
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read_at(s, 1234, buffers,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+}
+
+void test_5_arg_std_array_buffers_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::array<boost::asio::mutable_buffer, 2> buffers = { {
+ boost::asio::buffer(read_buf, 32),
+ boost::asio::buffer(read_buf) + 32 } };
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read_at(s, 1234, buffers,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+}
+
+void test_5_arg_vector_buffers_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ char read_buf[sizeof(read_data)];
+ std::vector<boost::asio::mutable_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(read_buf, 32));
+ buffers.push_back(boost::asio::buffer(read_buf) + 32);
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ bool called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ memset(read_buf, 0, sizeof(read_buf));
+ called = false;
+ boost::asio::async_read_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ memset(read_buf, 0, sizeof(read_buf));
+ int i = boost::asio::async_read_at(s, 1234, buffers,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(read_data)));
+}
+
+void test_5_arg_streambuf_async_read_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::streambuf sb(sizeof(read_data));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ bool called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 50));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 50));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_read_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 1));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_read_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 10));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_read_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), 42));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb, old_style_transfer_all,
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 0, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb.consume(sb.size());
+ called = false;
+ boost::asio::async_read_at(s, 1234, sb, short_transfer(),
+ bindns::bind(async_read_handler,
+ _1, _2, sizeof(read_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(sb.size() == sizeof(read_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+
+ s.reset(read_data, sizeof(read_data));
+ sb.consume(sb.size());
+ int i = boost::asio::async_read_at(s, 1234, sb,
+ short_transfer(), archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(1234, sb.data(), sizeof(read_data)));
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "read_at",
+ BOOST_ASIO_TEST_CASE(test_3_arg_mutable_buffer_read_at)
+ BOOST_ASIO_TEST_CASE(test_3_arg_vector_buffers_read_at)
+ BOOST_ASIO_TEST_CASE(test_3_arg_streambuf_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_nothrow_mutable_buffer_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_nothrow_vector_buffers_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_nothrow_streambuf_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_mutable_buffer_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_vector_buffers_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_streambuf_read_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_mutable_buffer_read_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_vector_buffers_read_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_streambuf_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_mutable_buffer_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_boost_array_buffers_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_std_array_buffers_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_vector_buffers_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_streambuf_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_mutable_buffer_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_boost_array_buffers_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_std_array_buffers_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_vector_buffers_async_read_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_streambuf_async_read_at)
+)
diff --git a/src/boost/libs/asio/test/read_until.cpp b/src/boost/libs/asio/test/read_until.cpp
new file mode 100644
index 000000000..78d3d38e9
--- /dev/null
+++ b/src/boost/libs/asio/test/read_until.cpp
@@ -0,0 +1,1660 @@
+//
+// read_until.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/read_until.hpp>
+
+#include <cstring>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/streambuf.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+class test_stream
+{
+public:
+ typedef boost::asio::io_context::executor_type executor_type;
+
+ test_stream(boost::asio::io_context& io_context)
+ : io_context_(io_context),
+ length_(0),
+ position_(0),
+ next_read_length_(0)
+ {
+ }
+
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return io_context_.get_executor();
+ }
+
+ void reset(const void* data, size_t length)
+ {
+ using namespace std; // For memcpy.
+
+ BOOST_ASIO_CHECK(length <= max_length);
+
+ memcpy(data_, data, length);
+ length_ = length;
+ position_ = 0;
+ next_read_length_ = length;
+ }
+
+ void next_read_length(size_t length)
+ {
+ next_read_length_ = length;
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read_some(const Mutable_Buffers& buffers)
+ {
+ size_t n = boost::asio::buffer_copy(buffers,
+ boost::asio::buffer(data_, length_) + position_,
+ next_read_length_);
+ position_ += n;
+ return n;
+ }
+
+ template <typename Mutable_Buffers>
+ size_t read_some(const Mutable_Buffers& buffers,
+ boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return read_some(buffers);
+ }
+
+ template <typename Mutable_Buffers, typename Handler>
+ void async_read_some(const Mutable_Buffers& buffers, Handler handler)
+ {
+ size_t bytes_transferred = read_some(buffers);
+ boost::asio::post(get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(Handler)(handler),
+ boost::system::error_code(), bytes_transferred));
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ enum { max_length = 8192 };
+ char data_[max_length];
+ size_t length_;
+ size_t position_;
+ size_t next_read_length_;
+};
+
+static const char read_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void test_dynamic_string_read_until_char()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data1, data2;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
+ boost::system::error_code ec;
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ std::size_t length = boost::asio::read_until(s, sb1, 'Z');
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z');
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z');
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Z', ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Z', ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Z', ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Y', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Y', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Y', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+}
+
+void test_streambuf_read_until_char()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb1;
+ boost::asio::streambuf sb2(25);
+ boost::system::error_code ec;
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ std::size_t length = boost::asio::read_until(s, sb1, 'Z');
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z');
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z');
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, 'Z', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Z', ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Z', ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Z', ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Y', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Y', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, 'Y', ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void test_dynamic_string_read_until_string()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data1, data2;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
+ boost::system::error_code ec;
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ std::size_t length = boost::asio::read_until(s, sb1, "XYZ");
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ");
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ");
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "XYZ", ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "XYZ", ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "XYZ", ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "WXY", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "WXY", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "WXY", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+}
+
+void test_streambuf_read_until_string()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb1;
+ boost::asio::streambuf sb2(25);
+ boost::system::error_code ec;
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ std::size_t length = boost::asio::read_until(s, sb1, "XYZ");
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ");
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ");
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, "XYZ", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "XYZ", ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "XYZ", ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "XYZ", ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "WXY", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "WXY", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, "WXY", ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+class match_char
+{
+public:
+ explicit match_char(char c) : c_(c) {}
+
+ template <typename Iterator>
+ std::pair<Iterator, bool> operator()(
+ Iterator begin, Iterator end) const
+ {
+ Iterator i = begin;
+ while (i != end)
+ if (c_ == *i++)
+ return std::make_pair(i, true);
+ return std::make_pair(i, false);
+ }
+
+private:
+ char c_;
+};
+
+namespace boost {
+namespace asio {
+ template <> struct is_match_condition<match_char>
+ {
+ enum { value = true };
+ };
+} // namespace asio
+} // namespace boost
+
+void test_dynamic_string_read_until_match_condition()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data1, data2;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
+ boost::system::error_code ec;
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ std::size_t length = boost::asio::read_until(s, sb1, match_char('Z'));
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'));
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'));
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+}
+
+void test_streambuf_read_until_match_condition()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb1;
+ boost::asio::streambuf sb2(25);
+ boost::system::error_code ec;
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ std::size_t length = boost::asio::read_until(s, sb1, match_char('Z'));
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'));
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'));
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb1.consume(sb1.size());
+ length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ sb2.consume(sb2.size());
+ length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void async_read_handler(
+ const boost::system::error_code& err, boost::system::error_code* err_out,
+ std::size_t bytes_transferred, std::size_t* bytes_out, bool* called)
+{
+ *err_out = err;
+ *bytes_out = bytes_transferred;
+ *called = true;
+}
+
+void test_dynamic_string_async_read_until_char()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data1, data2;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
+ boost::system::error_code ec;
+ std::size_t length;
+ bool called;
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Y',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Y',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Y',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ int i = boost::asio::async_read_until(s, sb2, 'Y',
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+}
+
+void test_streambuf_async_read_until_char()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb1;
+ boost::asio::streambuf sb2(25);
+ boost::system::error_code ec;
+ std::size_t length;
+ bool called;
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Z',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Y',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Y',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, 'Y',
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ int i = boost::asio::async_read_until(s, sb2, 'Y',
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void test_dynamic_string_async_read_until_string()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data1, data2;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
+ boost::system::error_code ec;
+ std::size_t length;
+ bool called;
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "WXY",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "WXY",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "WXY",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ int i = boost::asio::async_read_until(s, sb2, "WXY",
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+}
+
+void test_streambuf_async_read_until_string()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb1;
+ boost::asio::streambuf sb2(25);
+ boost::system::error_code ec;
+ std::size_t length;
+ bool called;
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "XYZ",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "WXY",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "WXY",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, "WXY",
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ int i = boost::asio::async_read_until(s, sb2, "WXY",
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void test_dynamic_string_async_read_until_match_condition()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data1, data2;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
+ boost::system::error_code ec;
+ std::size_t length;
+ bool called;
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Y'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Y'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Y'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ int i = boost::asio::async_read_until(s, sb2, match_char('Y'),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+}
+
+void test_streambuf_async_read_until_match_condition()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb1;
+ boost::asio::streambuf sb2(25);
+ boost::system::error_code ec;
+ std::size_t length;
+ bool called;
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb1.consume(sb1.size());
+ boost::asio::async_read_until(s, sb1, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 26);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Z'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
+ BOOST_ASIO_CHECK(length == 0);
+
+ s.reset(read_data, sizeof(read_data));
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Y'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(1);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Y'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ s.next_read_length(10);
+ ec = boost::system::error_code();
+ length = 0;
+ called = false;
+ sb2.consume(sb2.size());
+ boost::asio::async_read_until(s, sb2, match_char('Y'),
+ bindns::bind(async_read_handler, _1, &ec,
+ _2, &length, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(!ec);
+ BOOST_ASIO_CHECK(length == 25);
+
+ s.reset(read_data, sizeof(read_data));
+ sb2.consume(sb2.size());
+ int i = boost::asio::async_read_until(s, sb2, match_char('Y'),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "read_until",
+ BOOST_ASIO_TEST_CASE(test_dynamic_string_read_until_char)
+ BOOST_ASIO_TEST_CASE(test_streambuf_read_until_char)
+ BOOST_ASIO_TEST_CASE(test_dynamic_string_read_until_string)
+ BOOST_ASIO_TEST_CASE(test_streambuf_read_until_string)
+ BOOST_ASIO_TEST_CASE(test_dynamic_string_read_until_match_condition)
+ BOOST_ASIO_TEST_CASE(test_streambuf_read_until_match_condition)
+ BOOST_ASIO_TEST_CASE(test_dynamic_string_async_read_until_char)
+ BOOST_ASIO_TEST_CASE(test_streambuf_async_read_until_char)
+ BOOST_ASIO_TEST_CASE(test_dynamic_string_async_read_until_string)
+ BOOST_ASIO_TEST_CASE(test_streambuf_async_read_until_string)
+ BOOST_ASIO_TEST_CASE(test_dynamic_string_async_read_until_match_condition)
+ BOOST_ASIO_TEST_CASE(test_streambuf_async_read_until_match_condition)
+)
diff --git a/src/boost/libs/asio/test/redirect_error.cpp b/src/boost/libs/asio/test/redirect_error.cpp
new file mode 100644
index 000000000..2cbcfcbcc
--- /dev/null
+++ b/src/boost/libs/asio/test/redirect_error.cpp
@@ -0,0 +1,25 @@
+//
+// redirect_error.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/redirect_error.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "redirect_error",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/serial_port.cpp b/src/boost/libs/asio/test/serial_port.cpp
new file mode 100644
index 000000000..a75c58338
--- /dev/null
+++ b/src/boost/libs/asio/test/serial_port.cpp
@@ -0,0 +1,173 @@
+//
+// serial_port.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/serial_port.hpp>
+
+#include "archetypes/async_result.hpp"
+#include <boost/asio/io_context.hpp>
+#include "unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// serial_port_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// serial_port compile and link correctly. Runtime failures are ignored.
+
+namespace serial_port_compile {
+
+struct write_some_handler
+{
+ write_some_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ write_some_handler(write_some_handler&&) {}
+private:
+ write_some_handler(const write_some_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+struct read_some_handler
+{
+ read_some_handler() {}
+ void operator()(const boost::system::error_code&, std::size_t) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ read_some_handler(read_some_handler&&) {}
+private:
+ read_some_handler(const read_some_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_SERIAL_PORT)
+ using namespace boost::asio;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ serial_port::baud_rate serial_port_option;
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_serial_port constructors.
+
+ serial_port port1(ioc);
+ serial_port port2(ioc, "null");
+ serial_port::native_handle_type native_port1 = port1.native_handle();
+#if defined(BOOST_ASIO_MSVC) && (_MSC_VER < 1910)
+ // Skip this on older MSVC due to mysterious ambiguous overload errors.
+#else
+ serial_port port3(ioc, native_port1);
+#endif
+
+ serial_port port4(ioc_ex);
+ serial_port port5(ioc_ex, "null");
+ serial_port::native_handle_type native_port2 = port1.native_handle();
+ serial_port port6(ioc_ex, native_port2);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ serial_port port7(std::move(port6));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_serial_port operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ port1 = serial_port(ioc);
+ port1 = std::move(port2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ serial_port::executor_type ex = port1.get_executor();
+ (void)ex;
+
+ // basic_serial_port functions.
+
+ serial_port::lowest_layer_type& lowest_layer = port1.lowest_layer();
+ (void)lowest_layer;
+
+ const serial_port& port8 = port1;
+ const serial_port::lowest_layer_type& lowest_layer2 = port8.lowest_layer();
+ (void)lowest_layer2;
+
+ port1.open("null");
+ port1.open("null", ec);
+
+ serial_port::native_handle_type native_port3 = port1.native_handle();
+ port1.assign(native_port3);
+ serial_port::native_handle_type native_port4 = port1.native_handle();
+ port1.assign(native_port4, ec);
+
+ bool is_open = port1.is_open();
+ (void)is_open;
+
+ port1.close();
+ port1.close(ec);
+
+ serial_port::native_handle_type native_port5 = port1.native_handle();
+ (void)native_port5;
+
+ port1.cancel();
+ port1.cancel(ec);
+
+ port1.set_option(serial_port_option);
+ port1.set_option(serial_port_option, ec);
+
+ port1.get_option(serial_port_option);
+ port1.get_option(serial_port_option, ec);
+
+ port1.send_break();
+ port1.send_break(ec);
+
+ port1.write_some(buffer(mutable_char_buffer));
+ port1.write_some(buffer(const_char_buffer));
+ port1.write_some(buffer(mutable_char_buffer), ec);
+ port1.write_some(buffer(const_char_buffer), ec);
+
+ port1.async_write_some(buffer(mutable_char_buffer), write_some_handler());
+ port1.async_write_some(buffer(const_char_buffer), write_some_handler());
+ int i1 = port1.async_write_some(buffer(mutable_char_buffer), lazy);
+ (void)i1;
+ int i2 = port1.async_write_some(buffer(const_char_buffer), lazy);
+ (void)i2;
+
+ port1.read_some(buffer(mutable_char_buffer));
+ port1.read_some(buffer(mutable_char_buffer), ec);
+
+ port1.async_read_some(buffer(mutable_char_buffer), read_some_handler());
+ int i3 = port1.async_read_some(buffer(mutable_char_buffer), lazy);
+ (void)i3;
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
+}
+
+} // namespace serial_port_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "serial_port",
+ BOOST_ASIO_TEST_CASE(serial_port_compile::test)
+)
diff --git a/src/boost/libs/asio/test/serial_port_base.cpp b/src/boost/libs/asio/test/serial_port_base.cpp
new file mode 100644
index 000000000..40015f149
--- /dev/null
+++ b/src/boost/libs/asio/test/serial_port_base.cpp
@@ -0,0 +1,99 @@
+//
+// serial_port_base.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/serial_port_base.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/serial_port.hpp>
+#include "unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// serial_port_base_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Verify that all options and and their accessors compile. Runtime failures are
+// ignored.
+
+namespace serial_port_base_compile {
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_SERIAL_PORT)
+ using namespace boost::asio;
+
+ try
+ {
+ io_context ioc;
+ serial_port port(ioc);
+
+ // baud_rate class.
+
+ serial_port_base::baud_rate baud_rate1(9600);
+ port.set_option(baud_rate1);
+ serial_port_base::baud_rate baud_rate2;
+ port.get_option(baud_rate2);
+ (void)static_cast<unsigned int>(baud_rate2.value());
+
+ // flow_control class.
+
+ serial_port_base::flow_control flow_control1(
+ serial_port_base::flow_control::none);
+ port.set_option(flow_control1);
+ serial_port_base::flow_control flow_control2;
+ port.get_option(flow_control2);
+ (void)static_cast<serial_port_base::flow_control::type>(
+ flow_control2.value());
+
+ // parity class.
+
+ serial_port_base::parity parity1(serial_port_base::parity::none);
+ port.set_option(parity1);
+ serial_port_base::parity parity2;
+ port.get_option(parity2);
+ (void)static_cast<serial_port_base::parity::type>(parity2.value());
+
+ // stop_bits class.
+
+ serial_port_base::stop_bits stop_bits1(serial_port_base::stop_bits::one);
+ port.set_option(stop_bits1);
+ serial_port_base::stop_bits stop_bits2;
+ port.get_option(stop_bits2);
+ (void)static_cast<serial_port_base::stop_bits::type>(stop_bits2.value());
+
+ // character_size class.
+
+ serial_port_base::character_size character_size1(8);
+ port.set_option(character_size1);
+ serial_port_base::character_size character_size2;
+ port.get_option(character_size2);
+ (void)static_cast<unsigned int>(character_size2.value());
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
+}
+
+} // namespace serial_port_base_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "serial_port_base",
+ BOOST_ASIO_TEST_CASE(serial_port_base_compile::test)
+)
diff --git a/src/boost/libs/asio/test/signal_set.cpp b/src/boost/libs/asio/test/signal_set.cpp
new file mode 100644
index 000000000..97f714f4d
--- /dev/null
+++ b/src/boost/libs/asio/test/signal_set.cpp
@@ -0,0 +1,95 @@
+//
+// signal_set.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/signal_set.hpp>
+
+#include "archetypes/async_result.hpp"
+#include <boost/asio/io_context.hpp>
+#include "unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// signal_set_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// signal_set compile and link correctly. Runtime failures are ignored.
+
+namespace signal_set_compile {
+
+void signal_handler(const boost::system::error_code&, int)
+{
+}
+
+void test()
+{
+ using namespace boost::asio;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_signal_set constructors.
+
+ signal_set set1(ioc);
+ signal_set set2(ioc, 1);
+ signal_set set3(ioc, 1, 2);
+ signal_set set4(ioc, 1, 2, 3);
+
+ signal_set set5(ioc_ex);
+ signal_set set6(ioc_ex, 1);
+ signal_set set7(ioc_ex, 1, 2);
+ signal_set set8(ioc_ex, 1, 2, 3);
+
+ // basic_io_object functions.
+
+ signal_set::executor_type ex = set1.get_executor();
+ (void)ex;
+
+ // basic_signal_set functions.
+
+ set1.add(1);
+ set1.add(1, ec);
+
+ set1.remove(1);
+ set1.remove(1, ec);
+
+ set1.clear();
+ set1.clear(ec);
+
+ set1.cancel();
+ set1.cancel(ec);
+
+ set1.async_wait(&signal_handler);
+ int i = set1.async_wait(lazy);
+ (void)i;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace signal_set_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "signal_set",
+ BOOST_ASIO_TEST_CASE(signal_set_compile::test)
+)
diff --git a/src/boost/libs/asio/test/socket_base.cpp b/src/boost/libs/asio/test/socket_base.cpp
new file mode 100644
index 000000000..9fbf49193
--- /dev/null
+++ b/src/boost/libs/asio/test/socket_base.cpp
@@ -0,0 +1,650 @@
+//
+// socket_base.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/socket_base.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include "unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// socket_base_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all nested classes, enums and constants in
+// socket_base compile and link correctly. Runtime failures are ignored.
+
+namespace socket_base_compile {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ ip::tcp::socket sock(ioc);
+ char buf[1024];
+
+ // shutdown_type enumeration.
+
+ sock.shutdown(socket_base::shutdown_receive);
+ sock.shutdown(socket_base::shutdown_send);
+ sock.shutdown(socket_base::shutdown_both);
+
+ // message_flags constants.
+
+ sock.receive(buffer(buf), socket_base::message_peek);
+ sock.receive(buffer(buf), socket_base::message_out_of_band);
+ sock.send(buffer(buf), socket_base::message_do_not_route);
+
+ // broadcast class.
+
+ socket_base::broadcast broadcast1(true);
+ sock.set_option(broadcast1);
+ socket_base::broadcast broadcast2;
+ sock.get_option(broadcast2);
+ broadcast1 = true;
+ (void)static_cast<bool>(broadcast1);
+ (void)static_cast<bool>(!broadcast1);
+ (void)static_cast<bool>(broadcast1.value());
+
+ // debug class.
+
+ socket_base::debug debug1(true);
+ sock.set_option(debug1);
+ socket_base::debug debug2;
+ sock.get_option(debug2);
+ debug1 = true;
+ (void)static_cast<bool>(debug1);
+ (void)static_cast<bool>(!debug1);
+ (void)static_cast<bool>(debug1.value());
+
+ // do_not_route class.
+
+ socket_base::do_not_route do_not_route1(true);
+ sock.set_option(do_not_route1);
+ socket_base::do_not_route do_not_route2;
+ sock.get_option(do_not_route2);
+ do_not_route1 = true;
+ (void)static_cast<bool>(do_not_route1);
+ (void)static_cast<bool>(!do_not_route1);
+ (void)static_cast<bool>(do_not_route1.value());
+
+ // keep_alive class.
+
+ socket_base::keep_alive keep_alive1(true);
+ sock.set_option(keep_alive1);
+ socket_base::keep_alive keep_alive2;
+ sock.get_option(keep_alive2);
+ keep_alive1 = true;
+ (void)static_cast<bool>(keep_alive1);
+ (void)static_cast<bool>(!keep_alive1);
+ (void)static_cast<bool>(keep_alive1.value());
+
+ // send_buffer_size class.
+
+ socket_base::send_buffer_size send_buffer_size1(1024);
+ sock.set_option(send_buffer_size1);
+ socket_base::send_buffer_size send_buffer_size2;
+ sock.get_option(send_buffer_size2);
+ send_buffer_size1 = 1;
+ (void)static_cast<int>(send_buffer_size1.value());
+
+ // send_low_watermark class.
+
+ socket_base::send_low_watermark send_low_watermark1(128);
+ sock.set_option(send_low_watermark1);
+ socket_base::send_low_watermark send_low_watermark2;
+ sock.get_option(send_low_watermark2);
+ send_low_watermark1 = 1;
+ (void)static_cast<int>(send_low_watermark1.value());
+
+ // receive_buffer_size class.
+
+ socket_base::receive_buffer_size receive_buffer_size1(1024);
+ sock.set_option(receive_buffer_size1);
+ socket_base::receive_buffer_size receive_buffer_size2;
+ sock.get_option(receive_buffer_size2);
+ receive_buffer_size1 = 1;
+ (void)static_cast<int>(receive_buffer_size1.value());
+
+ // receive_low_watermark class.
+
+ socket_base::receive_low_watermark receive_low_watermark1(128);
+ sock.set_option(receive_low_watermark1);
+ socket_base::receive_low_watermark receive_low_watermark2;
+ sock.get_option(receive_low_watermark2);
+ receive_low_watermark1 = 1;
+ (void)static_cast<int>(receive_low_watermark1.value());
+
+ // reuse_address class.
+
+ socket_base::reuse_address reuse_address1(true);
+ sock.set_option(reuse_address1);
+ socket_base::reuse_address reuse_address2;
+ sock.get_option(reuse_address2);
+ reuse_address1 = true;
+ (void)static_cast<bool>(reuse_address1);
+ (void)static_cast<bool>(!reuse_address1);
+ (void)static_cast<bool>(reuse_address1.value());
+
+ // linger class.
+
+ socket_base::linger linger1(true, 30);
+ sock.set_option(linger1);
+ socket_base::linger linger2;
+ sock.get_option(linger2);
+ linger1.enabled(true);
+ (void)static_cast<bool>(linger1.enabled());
+ linger1.timeout(1);
+ (void)static_cast<int>(linger1.timeout());
+
+ // out_of_band_inline class.
+
+ socket_base::out_of_band_inline out_of_band_inline1(true);
+ sock.set_option(out_of_band_inline1);
+ socket_base::out_of_band_inline out_of_band_inline2;
+ sock.get_option(out_of_band_inline2);
+ out_of_band_inline1 = true;
+ (void)static_cast<bool>(out_of_band_inline1);
+ (void)static_cast<bool>(!out_of_band_inline1);
+ (void)static_cast<bool>(out_of_band_inline1.value());
+
+ // enable_connection_aborted class.
+
+ socket_base::enable_connection_aborted enable_connection_aborted1(true);
+ sock.set_option(enable_connection_aborted1);
+ socket_base::enable_connection_aborted enable_connection_aborted2;
+ sock.get_option(enable_connection_aborted2);
+ enable_connection_aborted1 = true;
+ (void)static_cast<bool>(enable_connection_aborted1);
+ (void)static_cast<bool>(!enable_connection_aborted1);
+ (void)static_cast<bool>(enable_connection_aborted1.value());
+
+ // bytes_readable class.
+
+ socket_base::bytes_readable bytes_readable;
+ sock.io_control(bytes_readable);
+ std::size_t bytes = bytes_readable.get();
+ (void)bytes;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace socket_base_compile
+
+//------------------------------------------------------------------------------
+
+// socket_base_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the socket options and I/O
+// control commands defined in socket_base.
+
+namespace socket_base_runtime {
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ io_context ioc;
+ ip::udp::socket udp_sock(ioc, ip::udp::v4());
+ ip::tcp::socket tcp_sock(ioc, ip::tcp::v4());
+ ip::tcp::acceptor tcp_acceptor(ioc, ip::tcp::v4());
+ boost::system::error_code ec;
+
+ // broadcast class.
+
+ socket_base::broadcast broadcast1(true);
+ BOOST_ASIO_CHECK(broadcast1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(broadcast1));
+ BOOST_ASIO_CHECK(!!broadcast1);
+ udp_sock.set_option(broadcast1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::broadcast broadcast2;
+ udp_sock.get_option(broadcast2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(broadcast2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(broadcast2));
+ BOOST_ASIO_CHECK(!!broadcast2);
+
+ socket_base::broadcast broadcast3(false);
+ BOOST_ASIO_CHECK(!broadcast3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(broadcast3));
+ BOOST_ASIO_CHECK(!broadcast3);
+ udp_sock.set_option(broadcast3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::broadcast broadcast4;
+ udp_sock.get_option(broadcast4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(!broadcast4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(broadcast4));
+ BOOST_ASIO_CHECK(!broadcast4);
+
+ // debug class.
+
+ socket_base::debug debug1(true);
+ BOOST_ASIO_CHECK(debug1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(debug1));
+ BOOST_ASIO_CHECK(!!debug1);
+ udp_sock.set_option(debug1, ec);
+#if defined(__linux__)
+ // On Linux, only root can set SO_DEBUG.
+ bool not_root = (ec == boost::asio::error::access_denied);
+ BOOST_ASIO_CHECK(!ec || not_root);
+ BOOST_ASIO_WARN_MESSAGE(!ec, "Must be root to set debug socket option");
+#else // defined(__linux__)
+# if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+# else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+# endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+#endif // defined(__linux__)
+
+ socket_base::debug debug2;
+ udp_sock.get_option(debug2, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+# if defined(__linux__)
+ BOOST_ASIO_CHECK(debug2.value() || not_root);
+ BOOST_ASIO_CHECK(static_cast<bool>(debug2) || not_root);
+ BOOST_ASIO_CHECK(!!debug2 || not_root);
+# else // defined(__linux__)
+ BOOST_ASIO_CHECK(debug2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(debug2));
+ BOOST_ASIO_CHECK(!!debug2);
+# endif // defined(__linux__)
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ socket_base::debug debug3(false);
+ BOOST_ASIO_CHECK(!debug3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(debug3));
+ BOOST_ASIO_CHECK(!debug3);
+ udp_sock.set_option(debug3, ec);
+#if defined(__linux__)
+ BOOST_ASIO_CHECK(!ec || not_root);
+#else // defined(__linux__)
+# if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+# else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+# endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+#endif // defined(__linux__)
+
+ socket_base::debug debug4;
+ udp_sock.get_option(debug4, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+# if defined(__linux__)
+ BOOST_ASIO_CHECK(!debug4.value() || not_root);
+ BOOST_ASIO_CHECK(!static_cast<bool>(debug4) || not_root);
+ BOOST_ASIO_CHECK(!debug4 || not_root);
+# else // defined(__linux__)
+ BOOST_ASIO_CHECK(!debug4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(debug4));
+ BOOST_ASIO_CHECK(!debug4);
+# endif // defined(__linux__)
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ // do_not_route class.
+
+ socket_base::do_not_route do_not_route1(true);
+ BOOST_ASIO_CHECK(do_not_route1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(do_not_route1));
+ BOOST_ASIO_CHECK(!!do_not_route1);
+ udp_sock.set_option(do_not_route1, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ socket_base::do_not_route do_not_route2;
+ udp_sock.get_option(do_not_route2, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(do_not_route2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(do_not_route2));
+ BOOST_ASIO_CHECK(!!do_not_route2);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ socket_base::do_not_route do_not_route3(false);
+ BOOST_ASIO_CHECK(!do_not_route3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(do_not_route3));
+ BOOST_ASIO_CHECK(!do_not_route3);
+ udp_sock.set_option(do_not_route3, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ socket_base::do_not_route do_not_route4;
+ udp_sock.get_option(do_not_route4, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(!do_not_route4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(do_not_route4));
+ BOOST_ASIO_CHECK(!do_not_route4);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ // keep_alive class.
+
+ socket_base::keep_alive keep_alive1(true);
+ BOOST_ASIO_CHECK(keep_alive1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(keep_alive1));
+ BOOST_ASIO_CHECK(!!keep_alive1);
+ tcp_sock.set_option(keep_alive1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::keep_alive keep_alive2;
+ tcp_sock.get_option(keep_alive2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(keep_alive2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(keep_alive2));
+ BOOST_ASIO_CHECK(!!keep_alive2);
+
+ socket_base::keep_alive keep_alive3(false);
+ BOOST_ASIO_CHECK(!keep_alive3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(keep_alive3));
+ BOOST_ASIO_CHECK(!keep_alive3);
+ tcp_sock.set_option(keep_alive3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::keep_alive keep_alive4;
+ tcp_sock.get_option(keep_alive4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(!keep_alive4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(keep_alive4));
+ BOOST_ASIO_CHECK(!keep_alive4);
+
+ // send_buffer_size class.
+
+ socket_base::send_buffer_size send_buffer_size1(4096);
+ BOOST_ASIO_CHECK(send_buffer_size1.value() == 4096);
+ tcp_sock.set_option(send_buffer_size1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::send_buffer_size send_buffer_size2;
+ tcp_sock.get_option(send_buffer_size2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(send_buffer_size2.value() == 4096);
+
+ socket_base::send_buffer_size send_buffer_size3(16384);
+ BOOST_ASIO_CHECK(send_buffer_size3.value() == 16384);
+ tcp_sock.set_option(send_buffer_size3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::send_buffer_size send_buffer_size4;
+ tcp_sock.get_option(send_buffer_size4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(send_buffer_size4.value() == 16384);
+
+ // send_low_watermark class.
+
+ socket_base::send_low_watermark send_low_watermark1(4096);
+ BOOST_ASIO_CHECK(send_low_watermark1.value() == 4096);
+ tcp_sock.set_option(send_low_watermark1, ec);
+#if defined(WIN32) || defined(__linux__) || defined(__sun)
+ BOOST_ASIO_CHECK(!!ec); // Not supported on Windows, Linux or Solaris.
+#else
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif
+
+ socket_base::send_low_watermark send_low_watermark2;
+ tcp_sock.get_option(send_low_watermark2, ec);
+#if defined(WIN32) || defined(__sun)
+ BOOST_ASIO_CHECK(!!ec); // Not supported on Windows or Solaris.
+#elif defined(__linux__)
+ BOOST_ASIO_CHECK(!ec); // Not supported on Linux but can get value.
+#else
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(send_low_watermark2.value() == 4096);
+#endif
+
+ socket_base::send_low_watermark send_low_watermark3(8192);
+ BOOST_ASIO_CHECK(send_low_watermark3.value() == 8192);
+ tcp_sock.set_option(send_low_watermark3, ec);
+#if defined(WIN32) || defined(__linux__) || defined(__sun)
+ BOOST_ASIO_CHECK(!!ec); // Not supported on Windows, Linux or Solaris.
+#else
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif
+
+ socket_base::send_low_watermark send_low_watermark4;
+ tcp_sock.get_option(send_low_watermark4, ec);
+#if defined(WIN32) || defined(__sun)
+ BOOST_ASIO_CHECK(!!ec); // Not supported on Windows or Solaris.
+#elif defined(__linux__)
+ BOOST_ASIO_CHECK(!ec); // Not supported on Linux but can get value.
+#else
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(send_low_watermark4.value() == 8192);
+#endif
+
+ // receive_buffer_size class.
+
+ socket_base::receive_buffer_size receive_buffer_size1(4096);
+ BOOST_ASIO_CHECK(receive_buffer_size1.value() == 4096);
+ tcp_sock.set_option(receive_buffer_size1, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ socket_base::receive_buffer_size receive_buffer_size2;
+ tcp_sock.get_option(receive_buffer_size2, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK(!ec); // Not supported under Windows CE but can get value.
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(receive_buffer_size2.value() == 4096);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ socket_base::receive_buffer_size receive_buffer_size3(16384);
+ BOOST_ASIO_CHECK(receive_buffer_size3.value() == 16384);
+ tcp_sock.set_option(receive_buffer_size3, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ // Option is not supported under Windows CE.
+ BOOST_ASIO_CHECK_MESSAGE(ec == boost::asio::error::no_protocol_option,
+ ec.value() << ", " << ec.message());
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ socket_base::receive_buffer_size receive_buffer_size4;
+ tcp_sock.get_option(receive_buffer_size4, ec);
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK(!ec); // Not supported under Windows CE but can get value.
+#else // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(receive_buffer_size4.value() == 16384);
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+ // receive_low_watermark class.
+
+ socket_base::receive_low_watermark receive_low_watermark1(4096);
+ BOOST_ASIO_CHECK(receive_low_watermark1.value() == 4096);
+ tcp_sock.set_option(receive_low_watermark1, ec);
+#if defined(WIN32) || defined(__sun)
+ BOOST_ASIO_CHECK(!!ec); // Not supported on Windows or Solaris.
+#else
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif
+
+ socket_base::receive_low_watermark receive_low_watermark2;
+ tcp_sock.get_option(receive_low_watermark2, ec);
+#if defined(WIN32) || defined(__sun)
+ BOOST_ASIO_CHECK(!!ec); // Not supported on Windows or Solaris.
+#else
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(receive_low_watermark2.value() == 4096);
+#endif
+
+ socket_base::receive_low_watermark receive_low_watermark3(8192);
+ BOOST_ASIO_CHECK(receive_low_watermark3.value() == 8192);
+ tcp_sock.set_option(receive_low_watermark3, ec);
+#if defined(WIN32) || defined(__sun)
+ BOOST_ASIO_CHECK(!!ec); // Not supported on Windows or Solaris.
+#else
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+#endif
+
+ socket_base::receive_low_watermark receive_low_watermark4;
+ tcp_sock.get_option(receive_low_watermark4, ec);
+#if defined(WIN32) || defined(__sun)
+ BOOST_ASIO_CHECK(!!ec); // Not supported on Windows or Solaris.
+#else
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(receive_low_watermark4.value() == 8192);
+#endif
+
+ // reuse_address class.
+
+ socket_base::reuse_address reuse_address1(true);
+ BOOST_ASIO_CHECK(reuse_address1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(reuse_address1));
+ BOOST_ASIO_CHECK(!!reuse_address1);
+ udp_sock.set_option(reuse_address1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::reuse_address reuse_address2;
+ udp_sock.get_option(reuse_address2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(reuse_address2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(reuse_address2));
+ BOOST_ASIO_CHECK(!!reuse_address2);
+
+ socket_base::reuse_address reuse_address3(false);
+ BOOST_ASIO_CHECK(!reuse_address3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(reuse_address3));
+ BOOST_ASIO_CHECK(!reuse_address3);
+ udp_sock.set_option(reuse_address3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::reuse_address reuse_address4;
+ udp_sock.get_option(reuse_address4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(!reuse_address4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(reuse_address4));
+ BOOST_ASIO_CHECK(!reuse_address4);
+
+ // linger class.
+
+ socket_base::linger linger1(true, 60);
+ BOOST_ASIO_CHECK(linger1.enabled());
+ BOOST_ASIO_CHECK(linger1.timeout() == 60);
+ tcp_sock.set_option(linger1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::linger linger2;
+ tcp_sock.get_option(linger2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(linger2.enabled());
+ BOOST_ASIO_CHECK(linger2.timeout() == 60);
+
+ socket_base::linger linger3(false, 0);
+ BOOST_ASIO_CHECK(!linger3.enabled());
+ BOOST_ASIO_CHECK(linger3.timeout() == 0);
+ tcp_sock.set_option(linger3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::linger linger4;
+ tcp_sock.get_option(linger4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(!linger4.enabled());
+
+ // enable_connection_aborted class.
+
+ socket_base::enable_connection_aborted enable_connection_aborted1(true);
+ BOOST_ASIO_CHECK(enable_connection_aborted1.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(enable_connection_aborted1));
+ BOOST_ASIO_CHECK(!!enable_connection_aborted1);
+ tcp_acceptor.set_option(enable_connection_aborted1, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::enable_connection_aborted enable_connection_aborted2;
+ tcp_acceptor.get_option(enable_connection_aborted2, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(enable_connection_aborted2.value());
+ BOOST_ASIO_CHECK(static_cast<bool>(enable_connection_aborted2));
+ BOOST_ASIO_CHECK(!!enable_connection_aborted2);
+
+ socket_base::enable_connection_aborted enable_connection_aborted3(false);
+ BOOST_ASIO_CHECK(!enable_connection_aborted3.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(enable_connection_aborted3));
+ BOOST_ASIO_CHECK(!enable_connection_aborted3);
+ tcp_acceptor.set_option(enable_connection_aborted3, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+
+ socket_base::enable_connection_aborted enable_connection_aborted4;
+ tcp_acceptor.get_option(enable_connection_aborted4, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+ BOOST_ASIO_CHECK(!enable_connection_aborted4.value());
+ BOOST_ASIO_CHECK(!static_cast<bool>(enable_connection_aborted4));
+ BOOST_ASIO_CHECK(!enable_connection_aborted4);
+
+ // bytes_readable class.
+
+ socket_base::bytes_readable bytes_readable;
+ udp_sock.io_control(bytes_readable, ec);
+ BOOST_ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message());
+}
+
+} // namespace socket_base_runtime
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "socket_base",
+ BOOST_ASIO_TEST_CASE(socket_base_compile::test)
+ BOOST_ASIO_TEST_CASE(socket_base_runtime::test)
+)
diff --git a/src/boost/libs/asio/test/ssl/Jamfile.v2 b/src/boost/libs/asio/test/ssl/Jamfile.v2
new file mode 100644
index 000000000..fd6f550ed
--- /dev/null
+++ b/src/boost/libs/asio/test/ssl/Jamfile.v2
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2003-2020 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)
+#
+
+import os ;
+import feature ;
+
+lib ssl ;
+lib crypto ;
+
+lib socket ; # SOLARIS
+lib nsl ; # SOLARIS
+lib ws2_32 ; # NT
+lib mswsock ; # NT
+lib ipv6 ; # HPUX
+lib network ; # HAIKU
+
+local USE_SELECT =
+ <define>BOOST_ASIO_DISABLE_EPOLL
+ <define>BOOST_ASIO_DISABLE_KQUEUE
+ <define>BOOST_ASIO_DISABLE_IOCP
+ ;
+
+project
+ : requirements
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/system//boost_system
+ <library>/boost/chrono//boost_chrono
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <target-os>solaris:<library>socket
+ <target-os>solaris:<library>nsl
+ <target-os>windows:<define>_WIN32_WINNT=0x0501
+ <target-os>windows,<toolset>gcc:<library>ws2_32
+ <target-os>windows,<toolset>gcc:<library>mswsock
+ <target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+ <target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+ <target-os>hpux:<library>ipv6
+ <target-os>haiku:<library>network
+ ;
+
+test-suite "asio-ssl" :
+ [ compile context_base.cpp ]
+ [ compile context_base.cpp : $(USE_SELECT) : context_base_select ]
+ [ compile context.cpp ]
+ [ compile context.cpp : $(USE_SELECT) : context_select ]
+ [ compile error.cpp ]
+ [ compile error.cpp : $(USE_SELECT) : error_select ]
+ [ compile host_name_verification.cpp ]
+ [ compile host_name_verification.cpp : $(USE_SELECT) : host_name_verification_select ]
+ [ compile rfc2818_verification.cpp ]
+ [ compile rfc2818_verification.cpp : $(USE_SELECT) : rfc2818_verification_select ]
+ [ compile stream_base.cpp ]
+ [ compile stream_base.cpp : $(USE_SELECT) : stream_base_select ]
+ [ compile stream.cpp ]
+ [ compile stream.cpp : $(USE_SELECT) : stream_select ]
+ ;
diff --git a/src/boost/libs/asio/test/ssl/context.cpp b/src/boost/libs/asio/test/ssl/context.cpp
new file mode 100644
index 000000000..12b3d838b
--- /dev/null
+++ b/src/boost/libs/asio/test/ssl/context.cpp
@@ -0,0 +1,25 @@
+//
+// context.cpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ssl/context.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ssl/context",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ssl/context_base.cpp b/src/boost/libs/asio/test/ssl/context_base.cpp
new file mode 100644
index 000000000..a63af9dac
--- /dev/null
+++ b/src/boost/libs/asio/test/ssl/context_base.cpp
@@ -0,0 +1,25 @@
+//
+// context_base.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ssl/context_base.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ssl/context_base",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ssl/error.cpp b/src/boost/libs/asio/test/ssl/error.cpp
new file mode 100644
index 000000000..722abe448
--- /dev/null
+++ b/src/boost/libs/asio/test/ssl/error.cpp
@@ -0,0 +1,25 @@
+//
+// error.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ssl/error.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ssl/error",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ssl/host_name_verification.cpp b/src/boost/libs/asio/test/ssl/host_name_verification.cpp
new file mode 100644
index 000000000..783455a95
--- /dev/null
+++ b/src/boost/libs/asio/test/ssl/host_name_verification.cpp
@@ -0,0 +1,25 @@
+//
+// host_name_verification.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ssl/host_name_verification.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ssl/host_name_verification",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ssl/rfc2818_verification.cpp b/src/boost/libs/asio/test/ssl/rfc2818_verification.cpp
new file mode 100644
index 000000000..92d002e5b
--- /dev/null
+++ b/src/boost/libs/asio/test/ssl/rfc2818_verification.cpp
@@ -0,0 +1,25 @@
+//
+// rfc2818_verification.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ssl/rfc2818_verification.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ssl/rfc2818_verification",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ssl/stream.cpp b/src/boost/libs/asio/test/ssl/stream.cpp
new file mode 100644
index 000000000..007dd5f4c
--- /dev/null
+++ b/src/boost/libs/asio/test/ssl/stream.cpp
@@ -0,0 +1,191 @@
+//
+// stream.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ssl/stream.hpp>
+
+#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
+#include "../archetypes/async_result.hpp"
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// ssl_stream_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// ssl::stream::socket compile and link correctly. Runtime failures are ignored.
+
+namespace ssl_stream_compile {
+
+bool verify_callback(bool, boost::asio::ssl::verify_context&)
+{
+ return false;
+}
+
+void handshake_handler(const boost::system::error_code&)
+{
+}
+
+void buffered_handshake_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void shutdown_handler(const boost::system::error_code&)
+{
+}
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+ using namespace boost::asio;
+ namespace ip = boost::asio::ip;
+
+ try
+ {
+ io_context ioc;
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // ssl::stream constructors.
+
+ ssl::stream<ip::tcp::socket> stream1(ioc, context);
+ ip::tcp::socket socket1(ioc, ip::tcp::v4());
+ ssl::stream<ip::tcp::socket&> stream2(socket1, context);
+
+ // basic_io_object functions.
+
+ ssl::stream<ip::tcp::socket>::executor_type ex = stream1.get_executor();
+ (void)ex;
+
+ // ssl::stream functions.
+
+ SSL* ssl1 = stream1.native_handle();
+ (void)ssl1;
+
+ ssl::stream<ip::tcp::socket>::lowest_layer_type& lowest_layer
+ = stream1.lowest_layer();
+ (void)lowest_layer;
+
+ const ssl::stream<ip::tcp::socket>& stream3 = stream1;
+ const ssl::stream<ip::tcp::socket>::lowest_layer_type& lowest_layer2
+ = stream3.lowest_layer();
+ (void)lowest_layer2;
+
+ stream1.set_verify_mode(ssl::verify_none);
+ stream1.set_verify_mode(ssl::verify_none, ec);
+
+ stream1.set_verify_depth(1);
+ stream1.set_verify_depth(1, ec);
+
+ stream1.set_verify_callback(verify_callback);
+ stream1.set_verify_callback(verify_callback, ec);
+
+ stream1.handshake(ssl::stream_base::client);
+ stream1.handshake(ssl::stream_base::server);
+ stream1.handshake(ssl::stream_base::client, ec);
+ stream1.handshake(ssl::stream_base::server, ec);
+
+ stream1.handshake(ssl::stream_base::client, buffer(mutable_char_buffer));
+ stream1.handshake(ssl::stream_base::server, buffer(mutable_char_buffer));
+ stream1.handshake(ssl::stream_base::client, buffer(const_char_buffer));
+ stream1.handshake(ssl::stream_base::server, buffer(const_char_buffer));
+ stream1.handshake(ssl::stream_base::client,
+ buffer(mutable_char_buffer), ec);
+ stream1.handshake(ssl::stream_base::server,
+ buffer(mutable_char_buffer), ec);
+ stream1.handshake(ssl::stream_base::client,
+ buffer(const_char_buffer), ec);
+ stream1.handshake(ssl::stream_base::server,
+ buffer(const_char_buffer), ec);
+
+ stream1.async_handshake(ssl::stream_base::client, handshake_handler);
+ stream1.async_handshake(ssl::stream_base::server, handshake_handler);
+ int i1 = stream1.async_handshake(ssl::stream_base::client, lazy);
+ (void)i1;
+ int i2 = stream1.async_handshake(ssl::stream_base::server, lazy);
+ (void)i2;
+
+ stream1.async_handshake(ssl::stream_base::client,
+ buffer(mutable_char_buffer), buffered_handshake_handler);
+ stream1.async_handshake(ssl::stream_base::server,
+ buffer(mutable_char_buffer), buffered_handshake_handler);
+ stream1.async_handshake(ssl::stream_base::client,
+ buffer(const_char_buffer), buffered_handshake_handler);
+ stream1.async_handshake(ssl::stream_base::server,
+ buffer(const_char_buffer), buffered_handshake_handler);
+ int i3 = stream1.async_handshake(ssl::stream_base::client,
+ buffer(mutable_char_buffer), lazy);
+ (void)i3;
+ int i4 = stream1.async_handshake(ssl::stream_base::server,
+ buffer(mutable_char_buffer), lazy);
+ (void)i4;
+ int i5 = stream1.async_handshake(ssl::stream_base::client,
+ buffer(const_char_buffer), lazy);
+ (void)i5;
+ int i6 = stream1.async_handshake(ssl::stream_base::server,
+ buffer(const_char_buffer), lazy);
+ (void)i6;
+
+ stream1.shutdown();
+ stream1.shutdown(ec);
+
+ stream1.async_shutdown(shutdown_handler);
+ int i7 = stream1.async_shutdown(lazy);
+ (void)i7;
+
+ stream1.write_some(buffer(mutable_char_buffer));
+ stream1.write_some(buffer(const_char_buffer));
+ stream1.write_some(buffer(mutable_char_buffer), ec);
+ stream1.write_some(buffer(const_char_buffer), ec);
+
+ stream1.async_write_some(buffer(mutable_char_buffer), write_some_handler);
+ stream1.async_write_some(buffer(const_char_buffer), write_some_handler);
+ int i8 = stream1.async_write_some(buffer(mutable_char_buffer), lazy);
+ (void)i8;
+ int i9 = stream1.async_write_some(buffer(const_char_buffer), lazy);
+ (void)i9;
+
+ stream1.read_some(buffer(mutable_char_buffer));
+ stream1.read_some(buffer(mutable_char_buffer), ec);
+
+ stream1.async_read_some(buffer(mutable_char_buffer), read_some_handler);
+ int i10 = stream1.async_read_some(buffer(mutable_char_buffer), lazy);
+ (void)i10;
+ }
+ catch (std::exception&)
+ {
+ }
+}
+
+} // namespace ssl_stream_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ssl/stream",
+ BOOST_ASIO_TEST_CASE(ssl_stream_compile::test)
+)
diff --git a/src/boost/libs/asio/test/ssl/stream_base.cpp b/src/boost/libs/asio/test/ssl/stream_base.cpp
new file mode 100644
index 000000000..5d02e34ad
--- /dev/null
+++ b/src/boost/libs/asio/test/ssl/stream_base.cpp
@@ -0,0 +1,25 @@
+//
+// stream_base.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/ssl/stream_base.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ssl/stream_base",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/steady_timer.cpp b/src/boost/libs/asio/test/steady_timer.cpp
new file mode 100644
index 000000000..237f71c89
--- /dev/null
+++ b/src/boost/libs/asio/test/steady_timer.cpp
@@ -0,0 +1,30 @@
+//
+// steady_timer.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/steady_timer.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "steady_timer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/strand.cpp b/src/boost/libs/asio/test/strand.cpp
new file mode 100644
index 000000000..66e97b90b
--- /dev/null
+++ b/src/boost/libs/asio/test/strand.cpp
@@ -0,0 +1,263 @@
+//
+// strand.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/strand.hpp>
+
+#include <sstream>
+#include <boost/asio/executor.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/detail/thread.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/deadline_timer.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/steady_timer.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+using namespace boost::asio;
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = std;
+#endif
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+typedef deadline_timer timer;
+namespace chronons = boost::posix_time;
+#elif defined(BOOST_ASIO_HAS_CHRONO)
+typedef steady_timer timer;
+namespace chronons = boost::asio::chrono;
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+void increment(int* count)
+{
+ ++(*count);
+}
+
+void increment_without_lock(strand<io_context::executor_type>* s, int* count)
+{
+ BOOST_ASIO_CHECK(!s->running_in_this_thread());
+
+ int original_count = *count;
+
+ dispatch(*s, bindns::bind(increment, count));
+
+ // No other functions are currently executing through the locking dispatcher,
+ // so the previous call to dispatch should have successfully nested.
+ BOOST_ASIO_CHECK(*count == original_count + 1);
+}
+
+void increment_with_lock(strand<io_context::executor_type>* s, int* count)
+{
+ BOOST_ASIO_CHECK(s->running_in_this_thread());
+
+ int original_count = *count;
+
+ dispatch(*s, bindns::bind(increment, count));
+
+ // The current function already holds the strand's lock, so the
+ // previous call to dispatch should have successfully nested.
+ BOOST_ASIO_CHECK(*count == original_count + 1);
+}
+
+void sleep_increment(io_context* ioc, int* count)
+{
+ timer t(*ioc, chronons::seconds(2));
+ t.wait();
+
+ ++(*count);
+}
+
+void increment_by_a(int* count, int a)
+{
+ (*count) += a;
+}
+
+void increment_by_a_b(int* count, int a, int b)
+{
+ (*count) += a + b;
+}
+
+void increment_by_a_b_c(int* count, int a, int b, int c)
+{
+ (*count) += a + b + c;
+}
+
+void increment_by_a_b_c_d(int* count, int a, int b, int c, int d)
+{
+ (*count) += a + b + c + d;
+}
+
+void start_sleep_increments(io_context* ioc,
+ strand<io_context::executor_type>* s, int* count)
+{
+ // Give all threads a chance to start.
+ timer t(*ioc, chronons::seconds(2));
+ t.wait();
+
+ // Start three increments.
+ post(*s, bindns::bind(sleep_increment, ioc, count));
+ post(*s, bindns::bind(sleep_increment, ioc, count));
+ post(*s, bindns::bind(sleep_increment, ioc, count));
+}
+
+void throw_exception()
+{
+ throw 1;
+}
+
+void io_context_run(io_context* ioc)
+{
+ ioc->run();
+}
+
+void strand_test()
+{
+ io_context ioc;
+ strand<io_context::executor_type> s = make_strand(ioc);
+ int count = 0;
+
+ post(ioc, bindns::bind(increment_without_lock, &s, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 0;
+ ioc.restart();
+ post(s, bindns::bind(increment_with_lock, &s, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 1);
+
+ count = 0;
+ ioc.restart();
+ post(ioc, bindns::bind(start_sleep_increments, &ioc, &s, &count));
+ boost::asio::detail::thread thread1(bindns::bind(io_context_run, &ioc));
+ boost::asio::detail::thread thread2(bindns::bind(io_context_run, &ioc));
+
+ // Check all events run one after another even though there are two threads.
+ timer timer1(ioc, chronons::seconds(3));
+ timer1.wait();
+ BOOST_ASIO_CHECK(count == 0);
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.expires_at(timer1.expires_at() + chronons::seconds(2));
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.expires_at(timer1.expiry() + chronons::seconds(2));
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.wait();
+ BOOST_ASIO_CHECK(count == 1);
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.expires_at(timer1.expires_at() + chronons::seconds(2));
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.expires_at(timer1.expiry() + chronons::seconds(2));
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ timer1.wait();
+ BOOST_ASIO_CHECK(count == 2);
+
+ thread1.join();
+ thread2.join();
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 3);
+
+ count = 0;
+ int exception_count = 0;
+ ioc.restart();
+ post(s, throw_exception);
+ post(s, bindns::bind(increment, &count));
+ post(s, bindns::bind(increment, &count));
+ post(s, throw_exception);
+ post(s, bindns::bind(increment, &count));
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+ BOOST_ASIO_CHECK(exception_count == 0);
+
+ for (;;)
+ {
+ try
+ {
+ ioc.run();
+ break;
+ }
+ catch (int)
+ {
+ ++exception_count;
+ }
+ }
+
+ // The run() calls will not return until all work has finished.
+ BOOST_ASIO_CHECK(count == 3);
+ BOOST_ASIO_CHECK(exception_count == 2);
+
+ count = 0;
+ ioc.restart();
+
+ // Check for clean shutdown when handlers posted through an orphaned strand
+ // are abandoned.
+ {
+ strand<io_context::executor_type> s2 = make_strand(ioc.get_executor());
+ post(s2, bindns::bind(increment, &count));
+ post(s2, bindns::bind(increment, &count));
+ post(s2, bindns::bind(increment, &count));
+ }
+
+ // No handlers can be called until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+}
+
+void strand_conversion_test()
+{
+ io_context ioc;
+ strand<io_context::executor_type> s1 = make_strand(ioc);
+
+ // Converting constructors.
+
+ strand<executor> s2(s1);
+ strand<executor> s3 = strand<io_context::executor_type>(s1);
+
+ // Converting assignment.
+
+ s3 = s1;
+ s3 = strand<io_context::executor_type>(s1);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "strand",
+ BOOST_ASIO_TEST_CASE(strand_test)
+ BOOST_ASIO_COMPILE_TEST_CASE(strand_conversion_test)
+)
diff --git a/src/boost/libs/asio/test/streambuf.cpp b/src/boost/libs/asio/test/streambuf.cpp
new file mode 100644
index 000000000..6c17167cb
--- /dev/null
+++ b/src/boost/libs/asio/test/streambuf.cpp
@@ -0,0 +1,62 @@
+//
+// streambuf.cpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/streambuf.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include "unit_test.hpp"
+
+void streambuf_test()
+{
+ boost::asio::streambuf sb;
+
+ sb.sputn("abcd", 4);
+
+ BOOST_ASIO_CHECK(sb.size() == 4);
+
+ for (int i = 0; i < 100; ++i)
+ {
+ sb.consume(3);
+
+ BOOST_ASIO_CHECK(sb.size() == 1);
+
+ char buf[1];
+ sb.sgetn(buf, 1);
+
+ BOOST_ASIO_CHECK(sb.size() == 0);
+
+ sb.sputn("ab", 2);
+
+ BOOST_ASIO_CHECK(sb.size() == 2);
+
+ boost::asio::buffer_copy(sb.prepare(10), boost::asio::buffer("cd", 2));
+ sb.commit(2);
+
+ BOOST_ASIO_CHECK(sb.size() == 4);
+ }
+
+ BOOST_ASIO_CHECK(sb.size() == 4);
+
+ sb.consume(4);
+
+ BOOST_ASIO_CHECK(sb.size() == 0);
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "streambuf",
+ BOOST_ASIO_TEST_CASE(streambuf_test)
+)
diff --git a/src/boost/libs/asio/test/system_context.cpp b/src/boost/libs/asio/test/system_context.cpp
new file mode 100644
index 000000000..32d08bf61
--- /dev/null
+++ b/src/boost/libs/asio/test/system_context.cpp
@@ -0,0 +1,30 @@
+//
+// system_context.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/system_context.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "system_context",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/system_executor.cpp b/src/boost/libs/asio/test/system_executor.cpp
new file mode 100644
index 000000000..2f286f438
--- /dev/null
+++ b/src/boost/libs/asio/test/system_executor.cpp
@@ -0,0 +1,30 @@
+//
+// system_executor.cpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/system_executor.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "system_executor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/system_timer.cpp b/src/boost/libs/asio/test/system_timer.cpp
new file mode 100644
index 000000000..88755bff8
--- /dev/null
+++ b/src/boost/libs/asio/test/system_timer.cpp
@@ -0,0 +1,399 @@
+//
+// system_timer.cpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/system_timer.hpp>
+
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_STD_CHRONO)
+
+#include <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/detail/thread.hpp>
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+void increment(int* count)
+{
+ ++(*count);
+}
+
+void decrement_to_zero(boost::asio::system_timer* t, int* count)
+{
+ if (*count > 0)
+ {
+ --(*count);
+
+ int before_value = *count;
+
+ t->expires_at(t->expiry() + boost::asio::chrono::seconds(1));
+ t->async_wait(bindns::bind(decrement_to_zero, t, count));
+
+ // Completion cannot nest, so count value should remain unchanged.
+ BOOST_ASIO_CHECK(*count == before_value);
+ }
+}
+
+void increment_if_not_cancelled(int* count,
+ const boost::system::error_code& ec)
+{
+ if (!ec)
+ ++(*count);
+}
+
+void cancel_timer(boost::asio::system_timer* t)
+{
+ std::size_t num_cancelled = t->cancel();
+ BOOST_ASIO_CHECK(num_cancelled == 1);
+}
+
+void cancel_one_timer(boost::asio::system_timer* t)
+{
+ std::size_t num_cancelled = t->cancel_one();
+ BOOST_ASIO_CHECK(num_cancelled == 1);
+}
+
+boost::asio::system_timer::time_point now()
+{
+ return boost::asio::system_timer::clock_type::now();
+}
+
+void system_timer_test()
+{
+ using boost::asio::chrono::seconds;
+ using boost::asio::chrono::microseconds;
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ const boost::asio::io_context::executor_type ioc_ex = ioc.get_executor();
+ int count = 0;
+
+ boost::asio::system_timer::time_point start = now();
+
+ boost::asio::system_timer t1(ioc, seconds(1));
+ t1.wait();
+
+ // The timer must block until after its expiry time.
+ boost::asio::system_timer::time_point end = now();
+ boost::asio::system_timer::time_point expected_end = start + seconds(1);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ start = now();
+
+ boost::asio::system_timer t2(ioc_ex, seconds(1) + microseconds(500000));
+ t2.wait();
+
+ // The timer must block until after its expiry time.
+ end = now();
+ expected_end = start + seconds(1) + microseconds(500000);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ t2.expires_at(t2.expiry() + seconds(1));
+ t2.wait();
+
+ // The timer must block until after its expiry time.
+ end = now();
+ expected_end += seconds(1);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ start = now();
+
+ t2.expires_after(seconds(1) + microseconds(200000));
+ t2.wait();
+
+ // The timer must block until after its expiry time.
+ end = now();
+ expected_end = start + seconds(1) + microseconds(200000);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ start = now();
+
+ boost::asio::system_timer t3(ioc, seconds(5));
+ t3.async_wait(bindns::bind(increment, &count));
+
+ // No completions can be delivered until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.run();
+
+ // The run() call will not return until all operations have finished, and
+ // this should not be until after the timer's expiry time.
+ BOOST_ASIO_CHECK(count == 1);
+ end = now();
+ expected_end = start + seconds(1);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ count = 3;
+ start = now();
+
+ boost::asio::system_timer t4(ioc, seconds(1));
+ t4.async_wait(bindns::bind(decrement_to_zero, &t4, &count));
+
+ // No completions can be delivered until run() is called.
+ BOOST_ASIO_CHECK(count == 3);
+
+ ioc.restart();
+ ioc.run();
+
+ // The run() call will not return until all operations have finished, and
+ // this should not be until after the timer's final expiry time.
+ BOOST_ASIO_CHECK(count == 0);
+ end = now();
+ expected_end = start + seconds(3);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ count = 0;
+ start = now();
+
+ boost::asio::system_timer t5(ioc, seconds(10));
+ t5.async_wait(bindns::bind(increment_if_not_cancelled, &count, _1));
+ boost::asio::system_timer t6(ioc, seconds(1));
+ t6.async_wait(bindns::bind(cancel_timer, &t5));
+
+ // No completions can be delivered until run() is called.
+ BOOST_ASIO_CHECK(count == 0);
+
+ ioc.restart();
+ ioc.run();
+
+ // The timer should have been cancelled, so count should not have changed.
+ // The total run time should not have been much more than 1 second (and
+ // certainly far less than 10 seconds).
+ BOOST_ASIO_CHECK(count == 0);
+ end = now();
+ expected_end = start + seconds(2);
+ BOOST_ASIO_CHECK(end < expected_end);
+
+ // Wait on the timer again without cancelling it. This time the asynchronous
+ // wait should run to completion and increment the counter.
+ t5.async_wait(bindns::bind(increment_if_not_cancelled, &count, _1));
+
+ ioc.restart();
+ ioc.run();
+
+ // The timer should not have been cancelled, so count should have changed.
+ // The total time since the timer was created should be more than 10 seconds.
+ BOOST_ASIO_CHECK(count == 1);
+ end = now();
+ expected_end = start + seconds(10);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+
+ count = 0;
+ start = now();
+
+ // Start two waits on a timer, one of which will be cancelled. The one
+ // which is not cancelled should still run to completion and increment the
+ // counter.
+ boost::asio::system_timer t7(ioc, seconds(3));
+ t7.async_wait(bindns::bind(increment_if_not_cancelled, &count, _1));
+ t7.async_wait(bindns::bind(increment_if_not_cancelled, &count, _1));
+ boost::asio::system_timer t8(ioc, seconds(1));
+ t8.async_wait(bindns::bind(cancel_one_timer, &t7));
+
+ ioc.restart();
+ ioc.run();
+
+ // One of the waits should not have been cancelled, so count should have
+ // changed. The total time since the timer was created should be more than 3
+ // seconds.
+ BOOST_ASIO_CHECK(count == 1);
+ end = now();
+ expected_end = start + seconds(3);
+ BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
+}
+
+struct timer_handler
+{
+ timer_handler() {}
+ void operator()(const boost::system::error_code&) {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ timer_handler(timer_handler&&) {}
+private:
+ timer_handler(const timer_handler&);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+};
+
+void system_timer_cancel_test()
+{
+ static boost::asio::io_context io_context;
+ struct timer
+ {
+ boost::asio::system_timer t;
+ timer() : t(io_context)
+ {
+ t.expires_at((boost::asio::system_timer::time_point::max)());
+ }
+ } timers[50];
+
+ timers[2].t.async_wait(timer_handler());
+ timers[41].t.async_wait(timer_handler());
+ for (int i = 10; i < 20; ++i)
+ timers[i].t.async_wait(timer_handler());
+
+ BOOST_ASIO_CHECK(timers[2].t.cancel() == 1);
+ BOOST_ASIO_CHECK(timers[41].t.cancel() == 1);
+ for (int i = 10; i < 20; ++i)
+ BOOST_ASIO_CHECK(timers[i].t.cancel() == 1);
+}
+
+struct custom_allocation_timer_handler
+{
+ custom_allocation_timer_handler(int* count) : count_(count) {}
+ void operator()(const boost::system::error_code&) {}
+ int* count_;
+};
+
+void* asio_handler_allocate(std::size_t size,
+ custom_allocation_timer_handler* handler)
+{
+ ++(*handler->count_);
+ return ::operator new(size);
+}
+
+void asio_handler_deallocate(void* pointer, std::size_t,
+ custom_allocation_timer_handler* handler)
+{
+ --(*handler->count_);
+ ::operator delete(pointer);
+}
+
+void system_timer_custom_allocation_test()
+{
+ static boost::asio::io_context io_context;
+ struct timer
+ {
+ boost::asio::system_timer t;
+ timer() : t(io_context) {}
+ } timers[100];
+
+ int allocation_count = 0;
+
+ for (int i = 0; i < 50; ++i)
+ {
+ timers[i].t.expires_at((boost::asio::system_timer::time_point::max)());
+ timers[i].t.async_wait(custom_allocation_timer_handler(&allocation_count));
+ }
+
+ for (int i = 50; i < 100; ++i)
+ {
+ timers[i].t.expires_at((boost::asio::system_timer::time_point::min)());
+ timers[i].t.async_wait(custom_allocation_timer_handler(&allocation_count));
+ }
+
+ for (int i = 0; i < 50; ++i)
+ timers[i].t.cancel();
+
+ io_context.run();
+
+ BOOST_ASIO_CHECK(allocation_count == 0);
+}
+
+void io_context_run(boost::asio::io_context* ioc)
+{
+ ioc->run();
+}
+
+void system_timer_thread_test()
+{
+ boost::asio::io_context ioc;
+ boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work
+ = boost::asio::make_work_guard(ioc);
+ boost::asio::system_timer t1(ioc);
+ boost::asio::system_timer t2(ioc);
+ int count = 0;
+
+ boost::asio::detail::thread th(bindns::bind(io_context_run, &ioc));
+
+ t2.expires_after(boost::asio::chrono::seconds(2));
+ t2.wait();
+
+ t1.expires_after(boost::asio::chrono::seconds(2));
+ t1.async_wait(bindns::bind(increment, &count));
+
+ t2.expires_after(boost::asio::chrono::seconds(4));
+ t2.wait();
+
+ ioc.stop();
+ th.join();
+
+ BOOST_ASIO_CHECK(count == 1);
+}
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+boost::asio::system_timer make_timer(boost::asio::io_context& ioc, int* count)
+{
+ boost::asio::system_timer t(ioc);
+ t.expires_after(boost::asio::chrono::seconds(1));
+ t.async_wait(bindns::bind(increment, count));
+ return t;
+}
+#endif
+
+void system_timer_move_test()
+{
+#if defined(BOOST_ASIO_HAS_MOVE)
+ boost::asio::io_context io_context1;
+ boost::asio::io_context io_context2;
+ int count = 0;
+
+ boost::asio::system_timer t1 = make_timer(io_context1, &count);
+ boost::asio::system_timer t2 = make_timer(io_context2, &count);
+ boost::asio::system_timer t3 = std::move(t1);
+
+ t2 = std::move(t1);
+
+ io_context2.run();
+
+ BOOST_ASIO_CHECK(count == 1);
+
+ io_context1.run();
+
+ BOOST_ASIO_CHECK(count == 2);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "system_timer",
+ BOOST_ASIO_TEST_CASE(system_timer_test)
+ BOOST_ASIO_TEST_CASE(system_timer_cancel_test)
+ BOOST_ASIO_TEST_CASE(system_timer_custom_allocation_test)
+ BOOST_ASIO_TEST_CASE(system_timer_thread_test)
+ BOOST_ASIO_TEST_CASE(system_timer_move_test)
+)
+#else // defined(BOOST_ASIO_HAS_STD_CHRONO)
+BOOST_ASIO_TEST_SUITE
+(
+ "system_timer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
+#endif // defined(BOOST_ASIO_HAS_STD_CHRONO)
diff --git a/src/boost/libs/asio/test/this_coro.cpp b/src/boost/libs/asio/test/this_coro.cpp
new file mode 100644
index 000000000..9a5c4eb77
--- /dev/null
+++ b/src/boost/libs/asio/test/this_coro.cpp
@@ -0,0 +1,25 @@
+//
+// this_coro.cpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/this_coro.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "this_coro",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/time_traits.cpp b/src/boost/libs/asio/test/time_traits.cpp
new file mode 100644
index 000000000..181d6fac1
--- /dev/null
+++ b/src/boost/libs/asio/test/time_traits.cpp
@@ -0,0 +1,25 @@
+//
+// time_traits.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/time_traits.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "time_traits",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ts/buffer.cpp b/src/boost/libs/asio/test/ts/buffer.cpp
new file mode 100644
index 000000000..2b2f86a4c
--- /dev/null
+++ b/src/boost/libs/asio/test/ts/buffer.cpp
@@ -0,0 +1,30 @@
+//
+// buffer.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/ts/buffer.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ts/buffer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ts/executor.cpp b/src/boost/libs/asio/test/ts/executor.cpp
new file mode 100644
index 000000000..97faf2b57
--- /dev/null
+++ b/src/boost/libs/asio/test/ts/executor.cpp
@@ -0,0 +1,30 @@
+//
+// executor.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/ts/executor.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ts/executor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ts/internet.cpp b/src/boost/libs/asio/test/ts/internet.cpp
new file mode 100644
index 000000000..d630723bd
--- /dev/null
+++ b/src/boost/libs/asio/test/ts/internet.cpp
@@ -0,0 +1,30 @@
+//
+// internet.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/ts/internet.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ts/internet",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ts/io_context.cpp b/src/boost/libs/asio/test/ts/io_context.cpp
new file mode 100644
index 000000000..c5fdbc178
--- /dev/null
+++ b/src/boost/libs/asio/test/ts/io_context.cpp
@@ -0,0 +1,30 @@
+//
+// io_context.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/ts/io_context.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ts/io_context",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ts/net.cpp b/src/boost/libs/asio/test/ts/net.cpp
new file mode 100644
index 000000000..12b1d5568
--- /dev/null
+++ b/src/boost/libs/asio/test/ts/net.cpp
@@ -0,0 +1,30 @@
+//
+// net.cpp
+// ~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/ts/net.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ts/net",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ts/netfwd.cpp b/src/boost/libs/asio/test/ts/netfwd.cpp
new file mode 100644
index 000000000..796d918b4
--- /dev/null
+++ b/src/boost/libs/asio/test/ts/netfwd.cpp
@@ -0,0 +1,33 @@
+//
+// netfwd.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/ts/netfwd.hpp>
+
+// Test that forward declarations don't conflict with full declarations.
+#include <boost/asio/ts/net.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ts/netfwd",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ts/socket.cpp b/src/boost/libs/asio/test/ts/socket.cpp
new file mode 100644
index 000000000..1722e8e18
--- /dev/null
+++ b/src/boost/libs/asio/test/ts/socket.cpp
@@ -0,0 +1,30 @@
+//
+// socket.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/ts/socket.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ts/socket",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/ts/timer.cpp b/src/boost/libs/asio/test/ts/timer.cpp
new file mode 100644
index 000000000..5e500f1f0
--- /dev/null
+++ b/src/boost/libs/asio/test/ts/timer.cpp
@@ -0,0 +1,30 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include <boost/asio/ts/timer.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "ts/timer",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/unit_test.hpp b/src/boost/libs/asio/test/unit_test.hpp
new file mode 100644
index 000000000..6d5a78478
--- /dev/null
+++ b/src/boost/libs/asio/test/unit_test.hpp
@@ -0,0 +1,177 @@
+//
+// unit_test.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 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 UNIT_TEST_HPP
+#define UNIT_TEST_HPP
+
+#include <boost/asio/detail/config.hpp>
+#include <iostream>
+#include <boost/asio/detail/atomic_count.hpp>
+
+#if defined(__sun)
+# include <stdlib.h> // Needed for lrand48.
+#endif // defined(__sun)
+
+#if defined(__BORLANDC__)
+
+// Prevent use of intrinsic for strcmp.
+# include <cstring>
+# undef strcmp
+
+// Suppress error about condition always being true.
+# pragma option -w-ccc
+
+#endif // defined(__BORLANDC__)
+
+#if defined(BOOST_ASIO_MSVC)
+# pragma warning (disable:4127)
+# pragma warning (push)
+# pragma warning (disable:4244)
+# pragma warning (disable:4702)
+#endif // defined(BOOST_ASIO_MSVC)
+
+#if !defined(BOOST_ASIO_TEST_IOSTREAM)
+# define BOOST_ASIO_TEST_IOSTREAM std::cerr
+#endif // !defined(BOOST_ASIO_TEST_IOSTREAM)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+inline const char*& test_name()
+{
+ static const char* name = 0;
+ return name;
+}
+
+inline atomic_count& test_errors()
+{
+ static atomic_count errors(0);
+ return errors;
+}
+
+inline void begin_test_suite(const char* name)
+{
+ boost::asio::detail::test_name();
+ boost::asio::detail::test_errors();
+ BOOST_ASIO_TEST_IOSTREAM << name << " test suite begins" << std::endl;
+}
+
+inline int end_test_suite(const char* name)
+{
+ BOOST_ASIO_TEST_IOSTREAM << name << " test suite ends" << std::endl;
+ BOOST_ASIO_TEST_IOSTREAM << "\n*** ";
+ long errors = boost::asio::detail::test_errors();
+ if (errors == 0)
+ BOOST_ASIO_TEST_IOSTREAM << "No errors detected.";
+ else if (errors == 1)
+ BOOST_ASIO_TEST_IOSTREAM << "1 error detected.";
+ else
+ BOOST_ASIO_TEST_IOSTREAM << errors << " errors detected." << std::endl;
+ BOOST_ASIO_TEST_IOSTREAM << std::endl;
+ return errors == 0 ? 0 : 1;
+}
+
+template <void (*Test)()>
+inline void run_test(const char* name)
+{
+ test_name() = name;
+ long errors_before = boost::asio::detail::test_errors();
+ Test();
+ if (test_errors() == errors_before)
+ BOOST_ASIO_TEST_IOSTREAM << name << " passed" << std::endl;
+ else
+ BOOST_ASIO_TEST_IOSTREAM << name << " failed" << std::endl;
+}
+
+template <void (*)()>
+inline void compile_test(const char* name)
+{
+ BOOST_ASIO_TEST_IOSTREAM << name << " passed" << std::endl;
+}
+
+#if defined(BOOST_ASIO_NO_EXCEPTIONS)
+
+template <typename T>
+void throw_exception(const T& t)
+{
+ BOOST_ASIO_TEST_IOSTREAM << "Exception: " << t.what() << std::endl;
+ std::abort();
+}
+
+#endif // defined(BOOST_ASIO_NO_EXCEPTIONS)
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#define BOOST_ASIO_CHECK(expr) \
+ do { if (!(expr)) { \
+ BOOST_ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
+ << boost::asio::detail::test_name() << ": " \
+ << "check '" << #expr << "' failed" << std::endl; \
+ ++boost::asio::detail::test_errors(); \
+ } } while (0)
+
+#define BOOST_ASIO_CHECK_MESSAGE(expr, msg) \
+ do { if (!(expr)) { \
+ BOOST_ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
+ << boost::asio::detail::test_name() << ": " \
+ << msg << std::endl; \
+ ++boost::asio::detail::test_errors(); \
+ } } while (0)
+
+#define BOOST_ASIO_WARN_MESSAGE(expr, msg) \
+ do { if (!(expr)) { \
+ BOOST_ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
+ << boost::asio::detail::test_name() << ": " \
+ << msg << std::endl; \
+ } } while (0)
+
+#define BOOST_ASIO_ERROR(msg) \
+ do { \
+ BOOST_ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
+ << boost::asio::detail::test_name() << ": " \
+ << msg << std::endl; \
+ ++boost::asio::detail::test_errors(); \
+ } while (0)
+
+#define BOOST_ASIO_TEST_SUITE(name, tests) \
+ int main() \
+ { \
+ boost::asio::detail::begin_test_suite(name); \
+ tests \
+ return boost::asio::detail::end_test_suite(name); \
+ }
+
+#define BOOST_ASIO_TEST_CASE(test) \
+ boost::asio::detail::run_test<&test>(#test);
+
+#define BOOST_ASIO_COMPILE_TEST_CASE(test) \
+ boost::asio::detail::compile_test<&test>(#test);
+
+inline void null_test()
+{
+}
+
+#if defined(__GNUC__) && defined(_AIX)
+
+// AIX needs this symbol defined in asio, even if it doesn't do anything.
+int test_main(int, char**)
+{
+}
+
+#endif // defined(__GNUC__) && defined(_AIX)
+
+#if defined(BOOST_ASIO_MSVC)
+# pragma warning (pop)
+#endif // defined(BOOST_ASIO_MSVC)
+
+#endif // UNIT_TEST_HPP
diff --git a/src/boost/libs/asio/test/use_awaitable.cpp b/src/boost/libs/asio/test/use_awaitable.cpp
new file mode 100644
index 000000000..338576a73
--- /dev/null
+++ b/src/boost/libs/asio/test/use_awaitable.cpp
@@ -0,0 +1,25 @@
+//
+// use_awaitable.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/use_awaitable.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "use_awaitable",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/use_future.cpp b/src/boost/libs/asio/test/use_future.cpp
new file mode 100644
index 000000000..33d3f6187
--- /dev/null
+++ b/src/boost/libs/asio/test/use_future.cpp
@@ -0,0 +1,670 @@
+//
+// use_future.cpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/use_future.hpp>
+
+#include <string>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_STD_FUTURE)
+
+#include "archetypes/async_ops.hpp"
+
+void use_future_0_test()
+{
+ using boost::asio::use_future;
+ using namespace archetypes;
+
+ std::future<void> f;
+
+ f = async_op_0(use_future);
+ try
+ {
+ f.get();
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_0(true, use_future);
+ try
+ {
+ f.get();
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_0(false, use_future);
+ try
+ {
+ f.get();
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::operation_aborted);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_0(true, use_future);
+ try
+ {
+ f.get();
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_0(false, use_future);
+ try
+ {
+ f.get();
+ BOOST_ASIO_CHECK(false);
+ }
+ catch (std::exception& e)
+ {
+ BOOST_ASIO_CHECK(e.what() == std::string("blah"));
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+}
+
+void use_future_1_test()
+{
+ using boost::asio::use_future;
+ using namespace archetypes;
+
+ std::future<int> f;
+
+ f = async_op_1(use_future);
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_1(true, use_future);
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_1(false, use_future);
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(false);
+ (void)i;
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::operation_aborted);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_1(true, use_future);
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_1(false, use_future);
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(false);
+ (void)i;
+ }
+ catch (std::exception& e)
+ {
+ BOOST_ASIO_CHECK(e.what() == std::string("blah"));
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+}
+
+void use_future_2_test()
+{
+ using boost::asio::use_future;
+ using namespace archetypes;
+
+ std::future<std::tuple<int, double>> f;
+
+ f = async_op_2(use_future);
+ try
+ {
+ int i;
+ double d;
+ std::tie(i, d) = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ BOOST_ASIO_CHECK(d == 2.0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_2(true, use_future);
+ try
+ {
+ int i;
+ double d;
+ std::tie(i, d) = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ BOOST_ASIO_CHECK(d == 2.0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_2(false, use_future);
+ try
+ {
+ std::tuple<int, double> t = f.get();
+ BOOST_ASIO_CHECK(false);
+ (void)t;
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::operation_aborted);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_2(true, use_future);
+ try
+ {
+ int i;
+ double d;
+ std::tie(i, d) = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ BOOST_ASIO_CHECK(d == 2.0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_2(false, use_future);
+ try
+ {
+ std::tuple<int, double> t = f.get();
+ BOOST_ASIO_CHECK(false);
+ (void)t;
+ }
+ catch (std::exception& e)
+ {
+ BOOST_ASIO_CHECK(e.what() == std::string("blah"));
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+}
+
+void use_future_3_test()
+{
+ using boost::asio::use_future;
+ using namespace archetypes;
+
+ std::future<std::tuple<int, double, char>> f;
+
+ f = async_op_3(use_future);
+ try
+ {
+ int i;
+ double d;
+ char c;
+ std::tie(i, d, c) = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ BOOST_ASIO_CHECK(d == 2.0);
+ BOOST_ASIO_CHECK(c == 'a');
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_3(true, use_future);
+ try
+ {
+ int i;
+ double d;
+ char c;
+ std::tie(i, d, c) = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ BOOST_ASIO_CHECK(d == 2.0);
+ BOOST_ASIO_CHECK(c == 'a');
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_3(false, use_future);
+ try
+ {
+ std::tuple<int, double, char> t = f.get();
+ BOOST_ASIO_CHECK(false);
+ (void)t;
+ }
+ catch (boost::system::system_error& e)
+ {
+ BOOST_ASIO_CHECK(e.code() == boost::asio::error::operation_aborted);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_3(true, use_future);
+ try
+ {
+ int i;
+ double d;
+ char c;
+ std::tie(i, d, c) = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ BOOST_ASIO_CHECK(d == 2.0);
+ BOOST_ASIO_CHECK(c == 'a');
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_3(false, use_future);
+ try
+ {
+ std::tuple<int, double, char> t = f.get();
+ BOOST_ASIO_CHECK(false);
+ (void)t;
+ }
+ catch (std::exception& e)
+ {
+ BOOST_ASIO_CHECK(e.what() == std::string("blah"));
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+}
+
+int package_0()
+{
+ return 42;
+}
+
+int package_ec_0(boost::system::error_code ec)
+{
+ return ec ? 0 : 42;
+}
+
+int package_ex_0(std::exception_ptr ex)
+{
+ return ex ? 0 : 42;
+}
+
+void use_future_package_0_test()
+{
+ using boost::asio::use_future;
+ using namespace archetypes;
+
+ std::future<int> f;
+
+ f = async_op_0(use_future(package_0));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_0(true, use_future(&package_ec_0));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_0(false, use_future(package_ec_0));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_0(true, use_future(package_ex_0));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_0(false, use_future(package_ex_0));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+}
+
+int package_1(int i)
+{
+ return i;
+}
+
+int package_ec_1(boost::system::error_code ec, int i)
+{
+ return ec ? 0 : i;
+}
+
+int package_ex_1(std::exception_ptr ex, int i)
+{
+ return ex ? 0 : i;
+}
+
+void use_future_package_1_test()
+{
+ using boost::asio::use_future;
+ using namespace archetypes;
+
+ std::future<int> f;
+
+ f = async_op_1(use_future(package_1));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_1(true, use_future(package_ec_1));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_1(false, use_future(package_ec_1));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_1(true, use_future(package_ex_1));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_1(false, use_future(package_ex_1));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+}
+
+int package_2(int i, double)
+{
+ return i;
+}
+
+int package_ec_2(boost::system::error_code ec, int i, double)
+{
+ return ec ? 0 : i;
+}
+
+int package_ex_2(std::exception_ptr ex, int i, double)
+{
+ return ex ? 0 : i;
+}
+
+void use_future_package_2_test()
+{
+ using boost::asio::use_future;
+ using namespace archetypes;
+
+ std::future<int> f;
+
+ f = async_op_2(use_future(package_2));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_2(true, use_future(package_ec_2));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_2(false, use_future(package_ec_2));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_2(true, use_future(package_ex_2));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_2(false, use_future(package_ex_2));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+}
+
+int package_3(int i, double, char)
+{
+ return i;
+}
+
+int package_ec_3(boost::system::error_code ec, int i, double, char)
+{
+ return ec ? 0 : i;
+}
+
+int package_ex_3(std::exception_ptr ex, int i, double, char)
+{
+ return ex ? 0 : i;
+}
+
+void use_future_package_3_test()
+{
+ using boost::asio::use_future;
+ using namespace archetypes;
+
+ std::future<int> f;
+
+ f = async_op_3(use_future(package_3));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_3(true, use_future(package_ec_3));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ec_3(false, use_future(package_ec_3));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_3(true, use_future(package_ex_3));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 42);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+
+ f = async_op_ex_3(false, use_future(package_ex_3));
+ try
+ {
+ int i = f.get();
+ BOOST_ASIO_CHECK(i == 0);
+ }
+ catch (...)
+ {
+ BOOST_ASIO_CHECK(false);
+ }
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "use_future",
+ BOOST_ASIO_TEST_CASE(use_future_0_test)
+ BOOST_ASIO_TEST_CASE(use_future_1_test)
+ BOOST_ASIO_TEST_CASE(use_future_2_test)
+ BOOST_ASIO_TEST_CASE(use_future_3_test)
+ BOOST_ASIO_TEST_CASE(use_future_package_0_test)
+ BOOST_ASIO_TEST_CASE(use_future_package_1_test)
+ BOOST_ASIO_TEST_CASE(use_future_package_2_test)
+ BOOST_ASIO_TEST_CASE(use_future_package_3_test)
+)
+
+#else // defined(BOOST_ASIO_HAS_STD_FUTURE)
+
+BOOST_ASIO_TEST_SUITE
+(
+ "use_future",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
+
+#endif // defined(BOOST_ASIO_HAS_STD_FUTURE)
diff --git a/src/boost/libs/asio/test/uses_executor.cpp b/src/boost/libs/asio/test/uses_executor.cpp
new file mode 100644
index 000000000..fb4702b87
--- /dev/null
+++ b/src/boost/libs/asio/test/uses_executor.cpp
@@ -0,0 +1,25 @@
+//
+// uses_executor.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/uses_executor.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "uses_executor",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/wait_traits.cpp b/src/boost/libs/asio/test/wait_traits.cpp
new file mode 100644
index 000000000..50514710f
--- /dev/null
+++ b/src/boost/libs/asio/test/wait_traits.cpp
@@ -0,0 +1,25 @@
+//
+// wait_traits.cpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/wait_traits.hpp>
+
+#include "unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "wait_traits",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/windows/basic_object_handle.cpp b/src/boost/libs/asio/test/windows/basic_object_handle.cpp
new file mode 100644
index 000000000..d128873e3
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/basic_object_handle.cpp
@@ -0,0 +1,25 @@
+//
+// basic_object_handle.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/basic_object_handle.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_object_handle",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/windows/basic_overlapped_handle.cpp b/src/boost/libs/asio/test/windows/basic_overlapped_handle.cpp
new file mode 100644
index 000000000..bd9623165
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/basic_overlapped_handle.cpp
@@ -0,0 +1,25 @@
+//
+// basic_overlapped_handle.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/basic_overlapped_handle.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_overlapped_handle",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/windows/basic_random_access_handle.cpp b/src/boost/libs/asio/test/windows/basic_random_access_handle.cpp
new file mode 100644
index 000000000..925d068ca
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/basic_random_access_handle.cpp
@@ -0,0 +1,25 @@
+//
+// basic_random_access_handle.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/basic_random_access_handle.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_random_access_handle",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/windows/basic_stream_handle.cpp b/src/boost/libs/asio/test/windows/basic_stream_handle.cpp
new file mode 100644
index 000000000..b15d88d5e
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/basic_stream_handle.cpp
@@ -0,0 +1,25 @@
+//
+// basic_stream_handle.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/basic_stream_handle.hpp>
+
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "basic_stream_handle",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/windows/object_handle.cpp b/src/boost/libs/asio/test/windows/object_handle.cpp
new file mode 100644
index 000000000..66c016646
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/object_handle.cpp
@@ -0,0 +1,130 @@
+//
+// object_handle.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/object_handle.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include "../archetypes/async_result.hpp"
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// windows_object_handle_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// windows::object_handle compile and link correctly. Runtime failures are
+// ignored.
+
+namespace windows_object_handle_compile {
+
+void wait_handler(const boost::system::error_code&)
+{
+}
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+ using namespace boost::asio;
+ namespace win = boost::asio::windows;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_object_handle constructors.
+
+ win::object_handle handle1(ioc);
+ HANDLE native_handle1 = INVALID_HANDLE_VALUE;
+#if defined(BOOST_ASIO_MSVC) && (_MSC_VER < 1910)
+ // Skip this on older MSVC due to mysterious ambiguous overload errors.
+#else
+ win::object_handle handle2(ioc, native_handle1);
+#endif
+
+ win::object_handle handle3(ioc_ex);
+ HANDLE native_handle2 = INVALID_HANDLE_VALUE;
+ win::object_handle handle4(ioc_ex, native_handle2);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ win::object_handle handle5(std::move(handle4));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_object_handle operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ handle1 = win::object_handle(ioc);
+ handle1 = std::move(handle3);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ win::object_handle::executor_type ex = handle1.get_executor();
+ (void)ex;
+
+ // basic_handle functions.
+
+ win::object_handle::lowest_layer_type& lowest_layer
+ = handle1.lowest_layer();
+ (void)lowest_layer;
+
+ const win::object_handle& handle6 = handle1;
+ const win::object_handle::lowest_layer_type& lowest_layer3
+ = handle6.lowest_layer();
+ (void)lowest_layer3;
+
+ HANDLE native_handle4 = INVALID_HANDLE_VALUE;
+ handle1.assign(native_handle4);
+
+ bool is_open = handle1.is_open();
+ (void)is_open;
+
+ handle1.close();
+ handle1.close(ec);
+
+ win::object_handle::native_handle_type native_handle3
+ = handle1.native_handle();
+ (void)native_handle3;
+
+ handle1.cancel();
+ handle1.cancel(ec);
+
+ // basic_object_handle functions.
+
+ handle1.wait();
+ handle1.wait(ec);
+
+ handle1.async_wait(&wait_handler);
+ int i1 = handle1.async_wait(lazy);
+ (void)i1;
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
+}
+
+} // namespace windows_object_handle_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "windows/object_handle",
+ BOOST_ASIO_TEST_CASE(windows_object_handle_compile::test)
+)
diff --git a/src/boost/libs/asio/test/windows/overlapped_handle.cpp b/src/boost/libs/asio/test/windows/overlapped_handle.cpp
new file mode 100644
index 000000000..c06d0a8c0
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/overlapped_handle.cpp
@@ -0,0 +1,26 @@
+//
+// overlapped_handle.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/overlapped_handle.hpp>
+
+#include <boost/asio.hpp>
+#include "../unit_test.hpp"
+
+BOOST_ASIO_TEST_SUITE
+(
+ "windows/overlapped_handle",
+ BOOST_ASIO_TEST_CASE(null_test)
+)
diff --git a/src/boost/libs/asio/test/windows/overlapped_ptr.cpp b/src/boost/libs/asio/test/windows/overlapped_ptr.cpp
new file mode 100644
index 000000000..da20280b9
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/overlapped_ptr.cpp
@@ -0,0 +1,107 @@
+//
+// overlapped_ptr.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/overlapped_ptr.hpp>
+
+#include <boost/asio/executor.hpp>
+#include <boost/asio/io_context.hpp>
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// windows_overlapped_ptr_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// windows::overlapped_ptr compile and link correctly. Runtime failures are
+// ignored.
+
+namespace windows_overlapped_ptr_compile {
+
+void overlapped_handler_1(const boost::system::error_code&, std::size_t)
+{
+}
+
+struct overlapped_handler_2
+{
+ void operator()(const boost::system::error_code&, std::size_t)
+ {
+ }
+};
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
+ using namespace boost::asio;
+ namespace win = boost::asio::windows;
+
+ try
+ {
+ io_context ioc;
+ boost::asio::executor ex(ioc.get_executor());
+
+ // basic_overlapped_ptr constructors.
+
+ win::overlapped_ptr ptr1;
+
+ win::overlapped_ptr ptr2(ioc, &overlapped_handler_1);
+ win::overlapped_ptr ptr3(ioc, overlapped_handler_2());
+
+ win::overlapped_ptr ptr4(ioc.get_executor(), &overlapped_handler_1);
+ win::overlapped_ptr ptr5(ioc.get_executor(), overlapped_handler_2());
+ win::overlapped_ptr ptr6(ex, &overlapped_handler_1);
+ win::overlapped_ptr ptr7(ex, overlapped_handler_2());
+
+ // overlapped_ptr functions.
+
+ ptr1.reset();
+
+ ptr2.reset(ioc, &overlapped_handler_1);
+ ptr3.reset(ioc, overlapped_handler_2());
+
+ ptr2.reset(ioc.get_executor(), &overlapped_handler_1);
+ ptr3.reset(ioc.get_executor(), overlapped_handler_2());
+ ptr2.reset(ex, &overlapped_handler_1);
+ ptr3.reset(ex, overlapped_handler_2());
+
+ OVERLAPPED* ov1 = ptr1.get();
+ (void)ov1;
+
+ const win::overlapped_ptr& ptr8(ptr1);
+ const OVERLAPPED* ov2 = ptr4.get();
+ (void)ov2;
+
+ OVERLAPPED* ov3 = ptr1.release();
+ (void)ov3;
+
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ ptr1.complete(ec, bytes_transferred);
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
+}
+
+} // namespace windows_overlapped_ptr_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "windows/overlapped_ptr",
+ BOOST_ASIO_TEST_CASE(windows_overlapped_ptr_compile::test)
+)
diff --git a/src/boost/libs/asio/test/windows/random_access_handle.cpp b/src/boost/libs/asio/test/windows/random_access_handle.cpp
new file mode 100644
index 000000000..d2edcb0c4
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/random_access_handle.cpp
@@ -0,0 +1,155 @@
+//
+// random_access_handle.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/random_access_handle.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include "../archetypes/async_result.hpp"
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// windows_random_access_handle_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// windows::random_access_handle compile and link correctly. Runtime failures
+// are ignored.
+
+namespace windows_random_access_handle_compile {
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
+ using namespace boost::asio;
+ namespace win = boost::asio::windows;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ boost::asio::uint64_t offset = 0;
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_random_access_handle constructors.
+
+ win::random_access_handle handle1(ioc);
+ HANDLE native_handle1 = INVALID_HANDLE_VALUE;
+#if defined(BOOST_ASIO_MSVC) && (_MSC_VER < 1910)
+ // Skip this on older MSVC due to mysterious ambiguous overload errors.
+#else
+ win::random_access_handle handle2(ioc, native_handle1);
+#endif
+
+ win::random_access_handle handle3(ioc_ex);
+ HANDLE native_handle2 = INVALID_HANDLE_VALUE;
+ win::random_access_handle handle4(ioc_ex, native_handle2);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ win::random_access_handle handle5(std::move(handle4));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_random_access_handle operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ handle1 = win::random_access_handle(ioc);
+ handle1 = std::move(handle4);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ windows::random_access_handle::executor_type ex = handle1.get_executor();
+ (void)ex;
+
+ // basic_overlapped_handle functions.
+
+ win::random_access_handle::lowest_layer_type& lowest_layer
+ = handle1.lowest_layer();
+ (void)lowest_layer;
+
+ const win::random_access_handle& handle6 = handle1;
+ const win::random_access_handle::lowest_layer_type& lowest_layer2
+ = handle6.lowest_layer();
+ (void)lowest_layer2;
+
+ HANDLE native_handle3 = INVALID_HANDLE_VALUE;
+ handle1.assign(native_handle3);
+
+ bool is_open = handle1.is_open();
+ (void)is_open;
+
+ handle1.close();
+ handle1.close(ec);
+
+ win::random_access_handle::native_handle_type native_handle4
+ = handle1.native_handle();
+ (void)native_handle4;
+
+ handle1.cancel();
+ handle1.cancel(ec);
+
+ // basic_random_access_handle functions.
+
+ handle1.write_some_at(offset, buffer(mutable_char_buffer));
+ handle1.write_some_at(offset, buffer(const_char_buffer));
+ handle1.write_some_at(offset, buffer(mutable_char_buffer), ec);
+ handle1.write_some_at(offset, buffer(const_char_buffer), ec);
+
+ handle1.async_write_some_at(offset,
+ buffer(mutable_char_buffer), &write_some_handler);
+ handle1.async_write_some_at(offset,
+ buffer(const_char_buffer), &write_some_handler);
+ int i1 = handle1.async_write_some_at(offset,
+ buffer(mutable_char_buffer), lazy);
+ (void)i1;
+ int i2 = handle1.async_write_some_at(offset,
+ buffer(const_char_buffer), lazy);
+ (void)i2;
+
+ handle1.read_some_at(offset, buffer(mutable_char_buffer));
+ handle1.read_some_at(offset, buffer(mutable_char_buffer), ec);
+
+ handle1.async_read_some_at(offset,
+ buffer(mutable_char_buffer), &read_some_handler);
+ int i3 = handle1.async_read_some_at(offset,
+ buffer(mutable_char_buffer), lazy);
+ (void)i3;
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
+}
+
+} // namespace windows_random_access_handle_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "windows/random_access_handle",
+ BOOST_ASIO_TEST_CASE(windows_random_access_handle_compile::test)
+)
diff --git a/src/boost/libs/asio/test/windows/stream_handle.cpp b/src/boost/libs/asio/test/windows/stream_handle.cpp
new file mode 100644
index 000000000..a782454c9
--- /dev/null
+++ b/src/boost/libs/asio/test/windows/stream_handle.cpp
@@ -0,0 +1,148 @@
+//
+// stream_handle.cpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/windows/stream_handle.hpp>
+
+#include <boost/asio/io_context.hpp>
+#include "../archetypes/async_result.hpp"
+#include "../unit_test.hpp"
+
+//------------------------------------------------------------------------------
+
+// windows_stream_handle_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public member functions on the class
+// windows::stream_handle compile and link correctly. Runtime failures are
+// ignored.
+
+namespace windows_stream_handle_compile {
+
+void write_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void read_some_handler(const boost::system::error_code&, std::size_t)
+{
+}
+
+void test()
+{
+#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+ using namespace boost::asio;
+ namespace win = boost::asio::windows;
+
+ try
+ {
+ io_context ioc;
+ const io_context::executor_type ioc_ex = ioc.get_executor();
+ char mutable_char_buffer[128] = "";
+ const char const_char_buffer[128] = "";
+ archetypes::lazy_handler lazy;
+ boost::system::error_code ec;
+
+ // basic_stream_handle constructors.
+
+ win::stream_handle handle1(ioc);
+ HANDLE native_handle1 = INVALID_HANDLE_VALUE;
+#if defined(BOOST_ASIO_MSVC) && (_MSC_VER < 1910)
+ // Skip this on older MSVC due to mysterious ambiguous overload errors.
+#else
+ win::stream_handle handle2(ioc, native_handle1);
+#endif
+
+ win::stream_handle handle3(ioc_ex);
+ HANDLE native_handle2 = INVALID_HANDLE_VALUE;
+ win::stream_handle handle4(ioc_ex, native_handle2);
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ win::stream_handle handle5(std::move(handle4));
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_stream_handle operators.
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ handle1 = win::stream_handle(ioc);
+ handle1 = std::move(handle4);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // basic_io_object functions.
+
+ windows::stream_handle::executor_type ex = handle1.get_executor();
+ (void)ex;
+
+ // basic_overlapped_handle functions.
+
+ win::stream_handle::lowest_layer_type& lowest_layer
+ = handle1.lowest_layer();
+ (void)lowest_layer;
+
+ const win::stream_handle& handle6 = handle1;
+ const win::stream_handle::lowest_layer_type& lowest_layer2
+ = handle6.lowest_layer();
+ (void)lowest_layer2;
+
+ HANDLE native_handle3 = INVALID_HANDLE_VALUE;
+ handle1.assign(native_handle3);
+
+ bool is_open = handle1.is_open();
+ (void)is_open;
+
+ handle1.close();
+ handle1.close(ec);
+
+ win::stream_handle::native_handle_type native_handle4
+ = handle1.native_handle();
+ (void)native_handle4;
+
+ handle1.cancel();
+ handle1.cancel(ec);
+
+ // basic_stream_handle functions.
+
+ handle1.write_some(buffer(mutable_char_buffer));
+ handle1.write_some(buffer(const_char_buffer));
+ handle1.write_some(buffer(mutable_char_buffer), ec);
+ handle1.write_some(buffer(const_char_buffer), ec);
+
+ handle1.async_write_some(buffer(mutable_char_buffer), &write_some_handler);
+ handle1.async_write_some(buffer(const_char_buffer), &write_some_handler);
+ int i1 = handle1.async_write_some(buffer(mutable_char_buffer), lazy);
+ (void)i1;
+ int i2 = handle1.async_write_some(buffer(const_char_buffer), lazy);
+ (void)i2;
+
+ handle1.read_some(buffer(mutable_char_buffer));
+ handle1.read_some(buffer(mutable_char_buffer), ec);
+
+ handle1.async_read_some(buffer(mutable_char_buffer), &read_some_handler);
+ int i3 = handle1.async_read_some(buffer(mutable_char_buffer), lazy);
+ (void)i3;
+ }
+ catch (std::exception&)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+}
+
+} // namespace windows_stream_handle_compile
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+ "windows/stream_handle",
+ BOOST_ASIO_TEST_CASE(windows_stream_handle_compile::test)
+)
diff --git a/src/boost/libs/asio/test/write.cpp b/src/boost/libs/asio/test/write.cpp
new file mode 100644
index 000000000..85d2470e2
--- /dev/null
+++ b/src/boost/libs/asio/test/write.cpp
@@ -0,0 +1,4904 @@
+//
+// write.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/write.hpp>
+
+#include <cstring>
+#include <vector>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/streambuf.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+#include <boost/array.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+using namespace std; // For memcmp, memcpy and memset.
+
+class test_stream
+{
+public:
+ typedef boost::asio::io_context::executor_type executor_type;
+
+ test_stream(boost::asio::io_context& io_context)
+ : io_context_(io_context),
+ length_(max_length),
+ position_(0),
+ next_write_length_(max_length)
+ {
+ memset(data_, 0, max_length);
+ }
+
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return io_context_.get_executor();
+ }
+
+ void reset(size_t length = max_length)
+ {
+ BOOST_ASIO_CHECK(length <= max_length);
+
+ memset(data_, 0, max_length);
+ length_ = length;
+ position_ = 0;
+ next_write_length_ = length;
+ }
+
+ void next_write_length(size_t length)
+ {
+ next_write_length_ = length;
+ }
+
+ template <typename Iterator>
+ bool check_buffers(Iterator begin, Iterator end, size_t length)
+ {
+ if (length != position_)
+ return false;
+
+ Iterator iter = begin;
+ size_t checked_length = 0;
+ for (; iter != end && checked_length < length; ++iter)
+ {
+ size_t buffer_length = boost::asio::buffer_size(*iter);
+ if (buffer_length > length - checked_length)
+ buffer_length = length - checked_length;
+ if (memcmp(data_ + checked_length, iter->data(), buffer_length) != 0)
+ return false;
+ checked_length += buffer_length;
+ }
+
+ return true;
+ }
+
+ template <typename Const_Buffers>
+ bool check_buffers(const Const_Buffers& buffers, size_t length)
+ {
+ return check_buffers(boost::asio::buffer_sequence_begin(buffers),
+ boost::asio::buffer_sequence_end(buffers), length);
+ }
+
+ template <typename Const_Buffers>
+ size_t write_some(const Const_Buffers& buffers)
+ {
+ size_t n = boost::asio::buffer_copy(
+ boost::asio::buffer(data_, length_) + position_,
+ buffers, next_write_length_);
+ position_ += n;
+ return n;
+ }
+
+ template <typename Const_Buffers>
+ size_t write_some(const Const_Buffers& buffers, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return write_some(buffers);
+ }
+
+ template <typename Const_Buffers, typename Handler>
+ void async_write_some(const Const_Buffers& buffers,
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ {
+ size_t bytes_transferred = write_some(buffers);
+ boost::asio::post(get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(Handler)(handler),
+ boost::system::error_code(), bytes_transferred));
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ enum { max_length = 8192 };
+ char data_[max_length];
+ size_t length_;
+ size_t position_;
+ size_t next_write_length_;
+};
+
+static const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static char mutable_write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void test_2_arg_zero_buffers_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+
+ size_t bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+}
+
+void test_2_arg_const_buffer_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_2_arg_mutable_buffer_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+}
+
+void test_2_arg_vector_buffers_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data, 39) + 32);
+ buffers.push_back(boost::asio::buffer(write_data) + 39);
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_2_arg_dynamic_string_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(write_data));
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ size_t bytes_transferred = boost::asio::write(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_3_arg_nothrow_zero_buffers_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == 0);
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_3_arg_nothrow_const_buffer_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_3_arg_nothrow_mutable_buffer_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_3_arg_nothrow_vector_buffers_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data, 39) + 32);
+ buffers.push_back(boost::asio::buffer(write_data) + 39);
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_3_arg_nothrow_dynamic_string_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(write_data));
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+bool old_style_transfer_all(const boost::system::error_code& ec,
+ size_t /*bytes_transferred*/)
+{
+ return !!ec;
+}
+
+struct short_transfer
+{
+ short_transfer() {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ short_transfer(short_transfer&&) {}
+#else // defined(BOOST_ASIO_HAS_MOVE)
+ short_transfer(const short_transfer&) {}
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+ size_t operator()(const boost::system::error_code& ec,
+ size_t /*bytes_transferred*/)
+ {
+ return !!ec ? 0 : 3;
+ }
+};
+
+void test_3_arg_const_buffer_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_3_arg_mutable_buffer_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+}
+
+void test_3_arg_vector_buffers_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data, 39) + 32);
+ buffers.push_back(boost::asio::buffer(write_data) + 39);
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_3_arg_dynamic_string_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(write_data));
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ size_t bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb, old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write(s, sb, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_4_arg_const_buffer_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_mutable_buffer_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_vector_buffers_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data, 39) + 32);
+ buffers.push_back(boost::asio::buffer(write_data) + 39);
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, buffers, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_dynamic_string_write()
+{
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(write_data));
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bytes_transferred = boost::asio::write(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write(s, sb, short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void async_write_handler(const boost::system::error_code& e,
+ size_t bytes_transferred, size_t expected_bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(!e);
+ BOOST_ASIO_CHECK(bytes_transferred == expected_bytes_transferred);
+}
+
+void test_3_arg_const_buffer_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_3_arg_mutable_buffer_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+}
+
+void test_3_arg_boost_array_buffers_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::array<boost::asio::const_buffer, 2> buffers = { {
+ boost::asio::buffer(write_data, 32),
+ boost::asio::buffer(write_data) + 32 } };
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+}
+
+void test_3_arg_std_array_buffers_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::array<boost::asio::const_buffer, 2> buffers = { {
+ boost::asio::buffer(write_data, 32),
+ boost::asio::buffer(write_data) + 32 } };
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+}
+
+void test_3_arg_vector_buffers_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data, 39) + 32);
+ buffers.push_back(boost::asio::buffer(write_data) + 39);
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_3_arg_dynamic_string_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(write_data));
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bool called = false;
+ boost::asio::async_write(s, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ int i = boost::asio::async_write(s, sb, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_3_arg_streambuf_async_write()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb;
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ bool called = false;
+ boost::asio::async_write(s, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ int i = boost::asio::async_write(s, sb, archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+void test_4_arg_const_buffer_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_4_arg_mutable_buffer_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_4_arg_boost_array_buffers_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::array<boost::asio::const_buffer, 2> buffers = { {
+ boost::asio::buffer(write_data, 32),
+ boost::asio::buffer(write_data) + 32 } };
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+}
+
+void test_4_arg_std_array_buffers_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::array<boost::asio::const_buffer, 2> buffers = { {
+ boost::asio::buffer(write_data, 32),
+ boost::asio::buffer(write_data) + 32 } };
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+}
+
+void test_4_arg_vector_buffers_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data, 39) + 32);
+ buffers.push_back(boost::asio::buffer(write_data) + 39);
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write(s, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_4_arg_dynamic_string_async_write()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ std::string data;
+ boost::asio::dynamic_string_buffer<char, std::string::traits_type,
+ std::string::allocator_type> sb
+ = boost::asio::dynamic_buffer(data, sizeof(write_data));
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ bool called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ data.assign(write_data, sizeof(write_data));
+ int i = boost::asio::async_write(s, sb, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+}
+
+void test_4_arg_streambuf_async_write()
+{
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_stream s(ioc);
+ boost::asio::streambuf sb;
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ bool called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 50));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write(s, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write(s, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write(s, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ int i = boost::asio::async_write(s, sb, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(buffers, sizeof(write_data)));
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "write",
+ BOOST_ASIO_TEST_CASE(test_2_arg_zero_buffers_write)
+ BOOST_ASIO_TEST_CASE(test_2_arg_const_buffer_write)
+ BOOST_ASIO_TEST_CASE(test_2_arg_mutable_buffer_write)
+ BOOST_ASIO_TEST_CASE(test_2_arg_vector_buffers_write)
+ BOOST_ASIO_TEST_CASE(test_2_arg_dynamic_string_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_zero_buffers_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_const_buffer_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_mutable_buffer_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_vector_buffers_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_nothrow_dynamic_string_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_const_buffer_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_mutable_buffer_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_vector_buffers_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_dynamic_string_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_const_buffer_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_mutable_buffer_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_vector_buffers_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_dynamic_string_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_const_buffer_async_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_mutable_buffer_async_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_boost_array_buffers_async_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_std_array_buffers_async_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_vector_buffers_async_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_dynamic_string_async_write)
+ BOOST_ASIO_TEST_CASE(test_3_arg_streambuf_async_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_const_buffer_async_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_mutable_buffer_async_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_boost_array_buffers_async_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_std_array_buffers_async_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_vector_buffers_async_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_dynamic_string_async_write)
+ BOOST_ASIO_TEST_CASE(test_4_arg_streambuf_async_write)
+)
diff --git a/src/boost/libs/asio/test/write_at.cpp b/src/boost/libs/asio/test/write_at.cpp
new file mode 100644
index 000000000..8730491f7
--- /dev/null
+++ b/src/boost/libs/asio/test/write_at.cpp
@@ -0,0 +1,7563 @@
+//
+// write_at.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/write_at.hpp>
+
+#include <cstring>
+#include "archetypes/async_result.hpp"
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/streambuf.hpp>
+#include "unit_test.hpp"
+
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <boost/bind/bind.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+# include <functional>
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+#include <boost/array.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+# include <array>
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+using namespace std; // For memcmp, memcpy and memset.
+
+class test_random_access_device
+{
+public:
+ typedef boost::asio::io_context::executor_type executor_type;
+
+ test_random_access_device(boost::asio::io_context& io_context)
+ : io_context_(io_context),
+ length_(max_length),
+ next_write_length_(max_length)
+ {
+ memset(data_, 0, max_length);
+ }
+
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return io_context_.get_executor();
+ }
+
+ void reset()
+ {
+ memset(data_, 0, max_length);
+ next_write_length_ = max_length;
+ }
+
+ void next_write_length(size_t length)
+ {
+ next_write_length_ = length;
+ }
+
+ template <typename Iterator>
+ bool check_buffers(boost::asio::uint64_t offset,
+ Iterator begin, Iterator end, size_t length)
+ {
+ if (offset + length > max_length)
+ return false;
+
+ Iterator iter = begin;
+ size_t checked_length = 0;
+ for (; iter != end && checked_length < length; ++iter)
+ {
+ size_t buffer_length = boost::asio::buffer_size(*iter);
+ if (buffer_length > length - checked_length)
+ buffer_length = length - checked_length;
+ if (memcmp(data_ + offset + checked_length,
+ iter->data(), buffer_length) != 0)
+ return false;
+ checked_length += buffer_length;
+ }
+
+ return true;
+ }
+
+ template <typename Const_Buffers>
+ bool check_buffers(boost::asio::uint64_t offset,
+ const Const_Buffers& buffers, size_t length)
+ {
+ return check_buffers(offset, boost::asio::buffer_sequence_begin(buffers),
+ boost::asio::buffer_sequence_end(buffers), length);
+ }
+
+ template <typename Const_Buffers>
+ size_t write_some_at(boost::asio::uint64_t offset,
+ const Const_Buffers& buffers)
+ {
+ return boost::asio::buffer_copy(
+ boost::asio::buffer(data_, length_) + offset,
+ buffers, next_write_length_);
+ }
+
+ template <typename Const_Buffers>
+ size_t write_some_at(boost::asio::uint64_t offset,
+ const Const_Buffers& buffers, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return write_some_at(offset, buffers);
+ }
+
+ template <typename Const_Buffers, typename Handler>
+ void async_write_some_at(boost::asio::uint64_t offset,
+ const Const_Buffers& buffers, BOOST_ASIO_MOVE_ARG(Handler) handler)
+ {
+ size_t bytes_transferred = write_some_at(offset, buffers);
+ boost::asio::post(get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(Handler)(handler),
+ boost::system::error_code(), bytes_transferred));
+ }
+
+private:
+ boost::asio::io_context& io_context_;
+ enum { max_length = 8192 };
+ char data_[max_length];
+ size_t length_;
+ size_t next_write_length_;
+};
+
+static const char write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static char mutable_write_data[]
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void test_3_arg_const_buffer_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+}
+
+void test_3_arg_mutable_buffer_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+}
+
+void test_3_arg_vector_buffers_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data) + 32);
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+}
+
+void test_4_arg_nothrow_const_buffer_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_nothrow_mutable_buffer_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_4_arg_nothrow_vector_buffers_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data) + 32);
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+bool old_style_transfer_all(const boost::system::error_code& ec,
+ size_t /*bytes_transferred*/)
+{
+ return !!ec;
+}
+
+struct short_transfer
+{
+ short_transfer() {}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ short_transfer(short_transfer&&) {}
+#else // defined(BOOST_ASIO_HAS_MOVE)
+ short_transfer(const short_transfer&) {}
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+ size_t operator()(const boost::system::error_code& ec,
+ size_t /*bytes_transferred*/)
+ {
+ return !!ec ? 0 : 3;
+ }
+};
+
+void test_4_arg_const_buffer_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+}
+
+void test_4_arg_mutable_buffer_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+}
+
+void test_4_arg_vector_buffers_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data) + 32);
+
+ s.reset();
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1));
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10));
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42));
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 0, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers, short_transfer());
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+}
+
+void test_5_arg_const_buffer_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_5_arg_mutable_buffer_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(mutable_write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void test_5_arg_vector_buffers_write_at()
+{
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data) + 32);
+
+ s.reset();
+ boost::system::error_code error;
+ size_t bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_all(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 50);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 1);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 10);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42), error);
+ BOOST_ASIO_CHECK(bytes_transferred == 42);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ old_style_transfer_all, error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(1);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 0, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+
+ s.reset();
+ s.next_write_length(10);
+ error = boost::system::error_code();
+ bytes_transferred = boost::asio::write_at(s, 1234, buffers,
+ short_transfer(), error);
+ BOOST_ASIO_CHECK(bytes_transferred == sizeof(write_data));
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+ BOOST_ASIO_CHECK(!error);
+}
+
+void async_write_handler(const boost::system::error_code& e,
+ size_t bytes_transferred, size_t expected_bytes_transferred, bool* called)
+{
+ *called = true;
+ BOOST_ASIO_CHECK(!e);
+ BOOST_ASIO_CHECK(bytes_transferred == expected_bytes_transferred);
+}
+
+void test_4_arg_const_buffer_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+}
+
+void test_4_arg_mutable_buffer_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+}
+
+void test_4_arg_boost_array_buffers_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::array<boost::asio::const_buffer, 2> buffers = { {
+ boost::asio::buffer(write_data, 32),
+ boost::asio::buffer(write_data) + 32 } };
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+}
+
+void test_4_arg_std_array_buffers_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ std::array<boost::asio::const_buffer, 2> buffers = { {
+ boost::asio::buffer(write_data, 32),
+ boost::asio::buffer(write_data) + 32 } };
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+}
+
+void test_4_arg_vector_buffers_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data) + 32);
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+}
+
+void test_4_arg_streambuf_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::streambuf sb;
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ bool called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ int i = boost::asio::async_write_at(s, 0, sb,
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+}
+
+void test_5_arg_const_buffer_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+}
+
+void test_5_arg_mutable_buffer_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::mutable_buffer buffers
+ = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(mutable_write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(mutable_write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+}
+
+void test_5_arg_boost_array_buffers_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::array<boost::asio::const_buffer, 2> buffers = { {
+ boost::asio::buffer(write_data, 32),
+ boost::asio::buffer(write_data) + 32 } };
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+#endif // defined(BOOST_ASIO_HAS_BOOST_ARRAY)
+}
+
+void test_5_arg_std_array_buffers_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ std::array<boost::asio::const_buffer, 2> buffers = { {
+ boost::asio::buffer(write_data, 32),
+ boost::asio::buffer(write_data) + 32 } };
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+}
+
+void test_5_arg_vector_buffers_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(write_data, 32));
+ buffers.push_back(boost::asio::buffer(write_data) + 32);
+
+ s.reset();
+ bool called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, buffers, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ int i = boost::asio::async_write_at(s, 0, buffers, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+}
+
+void test_5_arg_streambuf_async_write_at()
+{
+#if defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = boost;
+#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ namespace bindns = std;
+#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
+ using bindns::placeholders::_1;
+ using bindns::placeholders::_2;
+
+ boost::asio::io_context ioc;
+ test_random_access_device s(ioc);
+ boost::asio::streambuf sb;
+ boost::asio::const_buffer buffers
+ = boost::asio::buffer(write_data, sizeof(write_data));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ bool called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_all(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 50));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_at_least(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 50, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 50));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(1),
+ bindns::bind(async_write_handler,
+ _1, _2, 1, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 1));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(10),
+ bindns::bind(async_write_handler,
+ _1, _2, 10, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 10));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb,
+ boost::asio::transfer_exactly(42),
+ bindns::bind(async_write_handler,
+ _1, _2, 42, &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, 42));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 0, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb, old_style_transfer_all,
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 0, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(1);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 0, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ s.next_write_length(10);
+ called = false;
+ boost::asio::async_write_at(s, 1234, sb, short_transfer(),
+ bindns::bind(async_write_handler,
+ _1, _2, sizeof(write_data), &called));
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(called);
+ BOOST_ASIO_CHECK(s.check_buffers(1234, buffers, sizeof(write_data)));
+
+ s.reset();
+ sb.consume(sb.size());
+ sb.sputn(write_data, sizeof(write_data));
+ int i = boost::asio::async_write_at(s, 0, sb, short_transfer(),
+ archetypes::lazy_handler());
+ BOOST_ASIO_CHECK(i == 42);
+ ioc.restart();
+ ioc.run();
+ BOOST_ASIO_CHECK(s.check_buffers(0, buffers, sizeof(write_data)));
+}
+
+BOOST_ASIO_TEST_SUITE
+(
+ "write_at",
+ BOOST_ASIO_TEST_CASE(test_3_arg_const_buffer_write_at)
+ BOOST_ASIO_TEST_CASE(test_3_arg_mutable_buffer_write_at)
+ BOOST_ASIO_TEST_CASE(test_3_arg_vector_buffers_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_nothrow_const_buffer_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_nothrow_mutable_buffer_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_nothrow_vector_buffers_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_const_buffer_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_mutable_buffer_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_vector_buffers_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_const_buffer_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_mutable_buffer_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_vector_buffers_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_const_buffer_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_mutable_buffer_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_boost_array_buffers_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_std_array_buffers_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_vector_buffers_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_4_arg_streambuf_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_const_buffer_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_mutable_buffer_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_boost_array_buffers_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_std_array_buffers_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_vector_buffers_async_write_at)
+ BOOST_ASIO_TEST_CASE(test_5_arg_streambuf_async_write_at)
+)
diff --git a/src/boost/libs/asio/tools/handlerviz.pl b/src/boost/libs/asio/tools/handlerviz.pl
new file mode 100755
index 000000000..7e8de3df2
--- /dev/null
+++ b/src/boost/libs/asio/tools/handlerviz.pl
@@ -0,0 +1,299 @@
+#!/usr/bin/perl -w
+#
+# handlerviz.pl
+# ~~~~~~~~~~~~~
+#
+# A visualisation tool for post-processing the debug output generated by
+# Asio-based programs. Programs write this output to the standard error stream
+# when compiled with the define `BOOST_ASIO_ENABLE_HANDLER_TRACKING'.
+#
+# This tool generates output intended for use with the GraphViz tool `dot'. For
+# example, to convert output to a PNG image, use:
+#
+# perl handlerviz.pl < output.txt | dot -Tpng > output.png
+#
+# To convert to a PDF file, use:
+#
+# perl handlerviz.pl < output.txt | dot -Tpdf > output.pdf
+#
+# Copyright (c) 2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+
+use strict;
+
+my %nodes = ();
+my @edges = ();
+my %anon_nodes = ();
+my $anon_id = 0;
+my %all_nodes = ();
+
+#-------------------------------------------------------------------------------
+# Parse the debugging output and populate the nodes and edges.
+
+sub parse_debug_output()
+{
+ while (my $line = <>)
+ {
+ chomp($line);
+
+ if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/)
+ {
+ my $timestamp = $1;
+ my $action = $2;
+ my $description = $3;
+
+ # Handler creation.
+ if ($action =~ /^([0-9]+)\*([0-9]+)$/)
+ {
+ my $begin = $1;
+ my $end = $2;
+ my $label = $description;
+ $label =~ s/\./\\n/g;
+
+ if ($begin eq "0")
+ {
+ $begin = "a" . $anon_id++;
+ $anon_nodes{$begin} = $timestamp;
+ $all_nodes{"$timestamp-$begin"} = $begin;
+ }
+
+ my %edge = ( begin=>$begin, end=>$end, label=>$label );
+ push(@edges, \%edge);
+ }
+
+ # Begin handler invocation.
+ elsif ($action =~ /^>([0-9]+)$/)
+ {
+ my %new_node = ( label=>$description, entry=>$timestamp );
+ $new_node{content} = ();
+ $nodes{$1} = \%new_node;
+ $all_nodes{"$timestamp-$1"} = $1;
+ }
+
+ # End handler invocation.
+ elsif ($action =~ /^<([0-9]+)$/)
+ {
+ $nodes{$1}->{exit} = $timestamp;
+ }
+
+ # Handler threw exception.
+ elsif ($action =~ /^!([0-9]+)$/)
+ {
+ push(@{$nodes{$1}->{content}}, "exception");
+ }
+
+ # Handler was destroyed without being invoked.
+ elsif ($action =~ /^~([0-9]+)$/)
+ {
+ my %new_node = ( label=>"$timestamp destroyed" );
+ $new_node{content} = ();
+ $nodes{$1} = \%new_node;
+ $all_nodes{"$timestamp-$1"} = $1;
+ }
+
+ # Handler performed some operation.
+ elsif ($action =~ /^([0-9]+)$/)
+ {
+ if ($1 eq "0")
+ {
+ my $id = "a" . $anon_id++;
+ $anon_nodes{$id} = "$timestamp\\l$description";
+ $all_nodes{"$timestamp-$id"} = $id;
+ }
+ else
+ {
+ push(@{$nodes{$1}->{content}}, "$description");
+ }
+ }
+ }
+ }
+}
+
+#-------------------------------------------------------------------------------
+# Helper function to convert a string to escaped HTML text.
+
+sub escape($)
+{
+ my $text = shift;
+ $text =~ s/&/\&amp\;/g;
+ $text =~ s/</\&lt\;/g;
+ $text =~ s/>/\&gt\;/g;
+ $text =~ s/\t/ /g;
+ return $text;
+}
+
+#-------------------------------------------------------------------------------
+# Templates for dot output.
+
+my $graph_header = <<"EOF";
+/* Generated by asioviz.pl */
+digraph G
+{
+graph [ nodesep="1" ];
+node [ shape="box", fontsize="9" ];
+edge [ arrowtail="dot", fontsize="9" ];
+EOF
+
+my $graph_footer = <<"EOF";
+}
+EOF
+
+my $node_header = <<"EOF";
+"%name%"
+[
+label=<<table border="0" cellspacing="0">
+<tr><td align="left" bgcolor="gray" border="0">%label%</td></tr>
+EOF
+
+my $node_footer = <<"EOF";
+</table>>
+]
+EOF
+
+my $node_content = <<"EOF";
+<tr><td align="left" bgcolor="white" border="0">
+<font face="mono" point-size="9">%content%</font>
+</td></tr>
+EOF
+
+my $anon_nodes_header = <<"EOF";
+{
+node [ shape="record" ];
+EOF
+
+my $anon_nodes_footer = <<"EOF";
+}
+EOF
+
+my $anon_node = <<"EOF";
+"%name%" [ label="%label%", color="gray" ];
+EOF
+
+my $edges_header = <<"EOF";
+{
+edge [ style="dashed", arrowhead="open", weight="100" ];
+EOF
+
+my $edges_footer = <<"EOF";
+}
+EOF
+
+my $edge = <<"EOF";
+"%begin%" -> "%end%" [ label="%label%" ]
+EOF
+
+my $node_order_header = <<"EOF";
+{
+edge [ style="invis", weight="1" ];
+EOF
+
+my $node_order_footer = <<"EOF";
+}
+EOF
+
+my $node_order = <<"EOF";
+"%begin%" -> "%end%"
+EOF
+
+#-------------------------------------------------------------------------------
+# Generate dot output from the nodes and edges.
+
+sub print_nodes()
+{
+ foreach my $name (sort keys %nodes)
+ {
+ my $node = $nodes{$name};
+ my $entry = $node->{entry};
+ my $exit = $node->{exit};
+ my $label = escape($node->{label});
+ my $header = $node_header;
+ $header =~ s/%name%/$name/g;
+ $header =~ s/%label%/$label/g;
+ print($header);
+
+ my $line = $node_content;
+ my $content = $entry . " + " . sprintf("%.6f", $exit - $entry) . "s";
+ $line =~ s/%content%/$content/g;
+ print($line);
+
+ foreach my $content (@{$node->{content}})
+ {
+ $content = escape($content);
+ $content = " " if length($content) == 0;
+ my $line = $node_content;
+ $line =~ s/%content%/$content/g;
+ print($line);
+ }
+
+ print($node_footer);
+ }
+}
+
+sub print_anon_nodes()
+{
+ print($anon_nodes_header);
+ foreach my $name (sort keys %anon_nodes)
+ {
+ my $label = $anon_nodes{$name};
+ my $line = $anon_node;
+ $line =~ s/%name%/$name/g;
+ $line =~ s/%label%/$label/g;
+ print($line);
+ }
+ print($edges_footer);
+}
+
+sub print_edges()
+{
+ print($edges_header);
+ foreach my $e (@edges)
+ {
+ my $begin = $e->{begin};
+ my $end = $e->{end};
+ my $label = $e->{label};
+ my $line = $edge;
+ $line =~ s/%begin%/$begin/g;
+ $line =~ s/%end%/$end/g;
+ $line =~ s/%label%/$label/g;
+ print($line);
+ }
+ print($edges_footer);
+}
+
+sub print_node_order()
+{
+ my $prev = "";
+ print($node_order_header);
+ foreach my $name (sort keys %all_nodes)
+ {
+ if ($prev ne "")
+ {
+ my $begin = $prev;
+ my $end = $all_nodes{$name};
+ my $line = $node_order;
+ $line =~ s/%begin%/$begin/g;
+ $line =~ s/%end%/$end/g;
+ print($line);
+ }
+ $prev = $all_nodes{$name};
+ }
+ print($node_order_footer);
+}
+
+sub generate_dot()
+{
+ print($graph_header);
+ print_nodes();
+ print_anon_nodes();
+ print_edges();
+ print_node_order();
+ print($graph_footer);
+}
+
+#-------------------------------------------------------------------------------
+
+parse_debug_output();
+generate_dot();