1//
2// basic_seq_packet_socket.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
12#define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19#include <cstddef>
20#include <boost/asio/basic_socket.hpp>
21#include <boost/asio/detail/handler_type_requirements.hpp>
22#include <boost/asio/detail/throw_error.hpp>
23#include <boost/asio/error.hpp>
24
25#include <boost/asio/detail/push_options.hpp>
26
27namespace boost {
28namespace asio {
29
30#if !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
31#define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL
32
33// Forward declaration with defaulted arguments.
34template <typename Protocol, typename Executor = any_io_executor>
35class basic_seq_packet_socket;
36
37#endif // !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
38
39/// Provides sequenced packet socket functionality.
40/**
41 * The basic_seq_packet_socket class template provides asynchronous and blocking
42 * sequenced packet socket functionality.
43 *
44 * @par Thread Safety
45 * @e Distinct @e objects: Safe.@n
46 * @e Shared @e objects: Unsafe.
47 *
48 * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are
49 * thread safe with respect to each other, if the underlying operating system
50 * calls are also thread safe. This means that it is permitted to perform
51 * concurrent calls to these synchronous operations on a single socket object.
52 * Other synchronous operations, such as @c open or @c close, are not thread
53 * safe.
54 */
55template <typename Protocol, typename Executor>
56class basic_seq_packet_socket
57 : public basic_socket<Protocol, Executor>
58{
59private:
60 class initiate_async_send;
61 class initiate_async_receive_with_flags;
62
63public:
64 /// The type of the executor associated with the object.
65 typedef Executor executor_type;
66
67 /// Rebinds the socket type to another executor.
68 template <typename Executor1>
69 struct rebind_executor
70 {
71 /// The socket type when rebound to the specified executor.
72 typedef basic_seq_packet_socket<Protocol, Executor1> other;
73 };
74
75 /// The native representation of a socket.
76#if defined(GENERATING_DOCUMENTATION)
77 typedef implementation_defined native_handle_type;
78#else
79 typedef typename basic_socket<Protocol,
80 Executor>::native_handle_type native_handle_type;
81#endif
82
83 /// The protocol type.
84 typedef Protocol protocol_type;
85
86 /// The endpoint type.
87 typedef typename Protocol::endpoint endpoint_type;
88
89 /// Construct a basic_seq_packet_socket without opening it.
90 /**
91 * This constructor creates a sequenced packet socket without opening it. The
92 * socket needs to be opened and then connected or accepted before data can
93 * be sent or received on it.
94 *
95 * @param ex The I/O executor that the socket will use, by default, to
96 * dispatch handlers for any asynchronous operations performed on the socket.
97 */
98 explicit basic_seq_packet_socket(const executor_type& ex)
99 : basic_socket<Protocol, Executor>(ex)
100 {
101 }
102
103 /// Construct a basic_seq_packet_socket without opening it.
104 /**
105 * This constructor creates a sequenced packet socket without opening it. The
106 * socket needs to be opened and then connected or accepted before data can
107 * be sent or received on it.
108 *
109 * @param context An execution context which provides the I/O executor that
110 * the socket will use, by default, to dispatch handlers for any asynchronous
111 * operations performed on the socket.
112 */
113 template <typename ExecutionContext>
114 explicit basic_seq_packet_socket(ExecutionContext& context,
115 constraint_t<
116 is_convertible<ExecutionContext&, execution_context&>::value
117 > = 0)
118 : basic_socket<Protocol, Executor>(context)
119 {
120 }
121
122 /// Construct and open a basic_seq_packet_socket.
123 /**
124 * This constructor creates and opens a sequenced_packet socket. The socket
125 * needs to be connected or accepted before data can be sent or received on
126 * it.
127 *
128 * @param ex The I/O executor that the socket will use, by default, to
129 * dispatch handlers for any asynchronous operations performed on the socket.
130 *
131 * @param protocol An object specifying protocol parameters to be used.
132 *
133 * @throws boost::system::system_error Thrown on failure.
134 */
135 basic_seq_packet_socket(const executor_type& ex,
136 const protocol_type& protocol)
137 : basic_socket<Protocol, Executor>(ex, protocol)
138 {
139 }
140
141 /// Construct and open a basic_seq_packet_socket.
142 /**
143 * This constructor creates and opens a sequenced_packet socket. The socket
144 * needs to be connected or accepted before data can be sent or received on
145 * it.
146 *
147 * @param context An execution context which provides the I/O executor that
148 * the socket will use, by default, to dispatch handlers for any asynchronous
149 * operations performed on the socket.
150 *
151 * @param protocol An object specifying protocol parameters to be used.
152 *
153 * @throws boost::system::system_error Thrown on failure.
154 */
155 template <typename ExecutionContext>
156 basic_seq_packet_socket(ExecutionContext& context,
157 const protocol_type& protocol,
158 constraint_t<
159 is_convertible<ExecutionContext&, execution_context&>::value,
160 defaulted_constraint
161 > = defaulted_constraint())
162 : basic_socket<Protocol, Executor>(context, protocol)
163 {
164 }
165
166 /// Construct a basic_seq_packet_socket, opening it and binding it to the
167 /// given local endpoint.
168 /**
169 * This constructor creates a sequenced packet socket and automatically opens
170 * it bound to the specified endpoint on the local machine. The protocol used
171 * is the protocol associated with the given endpoint.
172 *
173 * @param ex The I/O executor that the socket will use, by default, to
174 * dispatch handlers for any asynchronous operations performed on the socket.
175 *
176 * @param endpoint An endpoint on the local machine to which the sequenced
177 * packet socket will be bound.
178 *
179 * @throws boost::system::system_error Thrown on failure.
180 */
181 basic_seq_packet_socket(const executor_type& ex,
182 const endpoint_type& endpoint)
183 : basic_socket<Protocol, Executor>(ex, endpoint)
184 {
185 }
186
187 /// Construct a basic_seq_packet_socket, opening it and binding it to the
188 /// given local endpoint.
189 /**
190 * This constructor creates a sequenced packet socket and automatically opens
191 * it bound to the specified endpoint on the local machine. The protocol used
192 * is the protocol associated with the given endpoint.
193 *
194 * @param context An execution context which provides the I/O executor that
195 * the socket will use, by default, to dispatch handlers for any asynchronous
196 * operations performed on the socket.
197 *
198 * @param endpoint An endpoint on the local machine to which the sequenced
199 * packet socket will be bound.
200 *
201 * @throws boost::system::system_error Thrown on failure.
202 */
203 template <typename ExecutionContext>
204 basic_seq_packet_socket(ExecutionContext& context,
205 const endpoint_type& endpoint,
206 constraint_t<
207 is_convertible<ExecutionContext&, execution_context&>::value
208 > = 0)
209 : basic_socket<Protocol, Executor>(context, endpoint)
210 {
211 }
212
213 /// Construct a basic_seq_packet_socket on an existing native socket.
214 /**
215 * This constructor creates a sequenced packet socket object to hold an
216 * existing native socket.
217 *
218 * @param ex The I/O executor that the socket will use, by default, to
219 * dispatch handlers for any asynchronous operations performed on the socket.
220 *
221 * @param protocol An object specifying protocol parameters to be used.
222 *
223 * @param native_socket The new underlying socket implementation.
224 *
225 * @throws boost::system::system_error Thrown on failure.
226 */
227 basic_seq_packet_socket(const executor_type& ex,
228 const protocol_type& protocol, const native_handle_type& native_socket)
229 : basic_socket<Protocol, Executor>(ex, protocol, native_socket)
230 {
231 }
232
233 /// Construct a basic_seq_packet_socket on an existing native socket.
234 /**
235 * This constructor creates a sequenced packet socket object to hold an
236 * existing native socket.
237 *
238 * @param context An execution context which provides the I/O executor that
239 * the socket will use, by default, to dispatch handlers for any asynchronous
240 * operations performed on the socket.
241 *
242 * @param protocol An object specifying protocol parameters to be used.
243 *
244 * @param native_socket The new underlying socket implementation.
245 *
246 * @throws boost::system::system_error Thrown on failure.
247 */
248 template <typename ExecutionContext>
249 basic_seq_packet_socket(ExecutionContext& context,
250 const protocol_type& protocol, const native_handle_type& native_socket,
251 constraint_t<
252 is_convertible<ExecutionContext&, execution_context&>::value
253 > = 0)
254 : basic_socket<Protocol, Executor>(context, protocol, native_socket)
255 {
256 }
257
258 /// Move-construct a basic_seq_packet_socket from another.
259 /**
260 * This constructor moves a sequenced packet socket from one object to
261 * another.
262 *
263 * @param other The other basic_seq_packet_socket object from which the move
264 * will occur.
265 *
266 * @note Following the move, the moved-from object is in the same state as if
267 * constructed using the @c basic_seq_packet_socket(const executor_type&)
268 * constructor.
269 */
270 basic_seq_packet_socket(basic_seq_packet_socket&& other) noexcept
271 : basic_socket<Protocol, Executor>(std::move(other))
272 {
273 }
274
275 /// Move-assign a basic_seq_packet_socket from another.
276 /**
277 * This assignment operator moves a sequenced packet socket from one object to
278 * another.
279 *
280 * @param other The other basic_seq_packet_socket object from which the move
281 * will occur.
282 *
283 * @note Following the move, the moved-from object is in the same state as if
284 * constructed using the @c basic_seq_packet_socket(const executor_type&)
285 * constructor.
286 */
287 basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
288 {
289 basic_socket<Protocol, Executor>::operator=(std::move(other));
290 return *this;
291 }
292
293 /// Move-construct a basic_seq_packet_socket from a socket of another protocol
294 /// type.
295 /**
296 * This constructor moves a sequenced packet socket from one object to
297 * another.
298 *
299 * @param other The other basic_seq_packet_socket object from which the move
300 * will occur.
301 *
302 * @note Following the move, the moved-from object is in the same state as if
303 * constructed using the @c basic_seq_packet_socket(const executor_type&)
304 * constructor.
305 */
306 template <typename Protocol1, typename Executor1>
307 basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,
308 constraint_t<
309 is_convertible<Protocol1, Protocol>::value
310 && is_convertible<Executor1, Executor>::value
311 > = 0)
312 : basic_socket<Protocol, Executor>(std::move(other))
313 {
314 }
315
316 /// Move-assign a basic_seq_packet_socket from a socket of another protocol
317 /// type.
318 /**
319 * This assignment operator moves a sequenced packet socket from one object to
320 * another.
321 *
322 * @param other The other basic_seq_packet_socket object from which the move
323 * will occur.
324 *
325 * @note Following the move, the moved-from object is in the same state as if
326 * constructed using the @c basic_seq_packet_socket(const executor_type&)
327 * constructor.
328 */
329 template <typename Protocol1, typename Executor1>
330 constraint_t<
331 is_convertible<Protocol1, Protocol>::value
332 && is_convertible<Executor1, Executor>::value,
333 basic_seq_packet_socket&
334 > operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other)
335 {
336 basic_socket<Protocol, Executor>::operator=(std::move(other));
337 return *this;
338 }
339
340 /// Destroys the socket.
341 /**
342 * This function destroys the socket, cancelling any outstanding asynchronous
343 * operations associated with the socket as if by calling @c cancel.
344 */
345 ~basic_seq_packet_socket()
346 {
347 }
348
349 /// Send some data on the socket.
350 /**
351 * This function is used to send data on the sequenced packet socket. The
352 * function call will block until the data has been sent successfully, or an
353 * until error occurs.
354 *
355 * @param buffers One or more data buffers to be sent on the socket.
356 *
357 * @param flags Flags specifying how the send call is to be made.
358 *
359 * @returns The number of bytes sent.
360 *
361 * @throws boost::system::system_error Thrown on failure.
362 *
363 * @par Example
364 * To send a single data buffer use the @ref buffer function as follows:
365 * @code
366 * socket.send(boost::asio::buffer(data, size), 0);
367 * @endcode
368 * See the @ref buffer documentation for information on sending multiple
369 * buffers in one go, and how to use it with arrays, boost::array or
370 * std::vector.
371 */
372 template <typename ConstBufferSequence>
373 std::size_t send(const ConstBufferSequence& buffers,
374 socket_base::message_flags flags)
375 {
376 boost::system::error_code ec;
377 std::size_t s = this->impl_.get_service().send(
378 this->impl_.get_implementation(), buffers, flags, ec);
379 boost::asio::detail::throw_error(err: ec, location: "send");
380 return s;
381 }
382
383 /// Send some data on the socket.
384 /**
385 * This function is used to send data on the sequenced packet socket. The
386 * function call will block the data has been sent successfully, or an until
387 * error occurs.
388 *
389 * @param buffers One or more data buffers to be sent on the socket.
390 *
391 * @param flags Flags specifying how the send call is to be made.
392 *
393 * @param ec Set to indicate what error occurred, if any.
394 *
395 * @returns The number of bytes sent. Returns 0 if an error occurred.
396 *
397 * @note The send operation may not transmit all of the data to the peer.
398 * Consider using the @ref write function if you need to ensure that all data
399 * is written before the blocking operation completes.
400 */
401 template <typename ConstBufferSequence>
402 std::size_t send(const ConstBufferSequence& buffers,
403 socket_base::message_flags flags, boost::system::error_code& ec)
404 {
405 return this->impl_.get_service().send(
406 this->impl_.get_implementation(), buffers, flags, ec);
407 }
408
409 /// Start an asynchronous send.
410 /**
411 * This function is used to asynchronously send data on the sequenced packet
412 * socket. It is an initiating function for an @ref asynchronous_operation,
413 * and always returns immediately.
414 *
415 * @param buffers One or more data buffers to be sent on the socket. Although
416 * the buffers object may be copied as necessary, ownership of the underlying
417 * memory blocks is retained by the caller, which must guarantee that they
418 * remain valid until the completion handler is called.
419 *
420 * @param flags Flags specifying how the send call is to be made.
421 *
422 * @param token The @ref completion_token that will be used to produce a
423 * completion handler, which will be called when the send completes.
424 * Potential completion tokens include @ref use_future, @ref use_awaitable,
425 * @ref yield_context, or a function object with the correct completion
426 * signature. The function signature of the completion handler must be:
427 * @code void handler(
428 * const boost::system::error_code& error, // Result of operation.
429 * std::size_t bytes_transferred // Number of bytes sent.
430 * ); @endcode
431 * Regardless of whether the asynchronous operation completes immediately or
432 * not, the completion handler will not be invoked from within this function.
433 * On immediate completion, invocation of the handler will be performed in a
434 * manner equivalent to using boost::asio::post().
435 *
436 * @par Completion Signature
437 * @code void(boost::system::error_code, std::size_t) @endcode
438 *
439 * @par Example
440 * To send a single data buffer use the @ref buffer function as follows:
441 * @code
442 * socket.async_send(boost::asio::buffer(data, size), 0, handler);
443 * @endcode
444 * See the @ref buffer documentation for information on sending multiple
445 * buffers in one go, and how to use it with arrays, boost::array or
446 * std::vector.
447 *
448 * @par Per-Operation Cancellation
449 * On POSIX or Windows operating systems, this asynchronous operation supports
450 * cancellation for the following boost::asio::cancellation_type values:
451 *
452 * @li @c cancellation_type::terminal
453 *
454 * @li @c cancellation_type::partial
455 *
456 * @li @c cancellation_type::total
457 */
458 template <typename ConstBufferSequence,
459 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
460 std::size_t)) WriteToken
461 = default_completion_token_t<executor_type>>
462 auto async_send(const ConstBufferSequence& buffers,
463 socket_base::message_flags flags,
464 WriteToken&& token
465 = default_completion_token_t<executor_type>())
466 -> decltype(
467 async_initiate<WriteToken,
468 void (boost::system::error_code, std::size_t)>(
469 declval<initiate_async_send>(), token, buffers, flags))
470 {
471 return async_initiate<WriteToken,
472 void (boost::system::error_code, std::size_t)>(
473 initiate_async_send(this), token, buffers, flags);
474 }
475
476 /// Receive some data on the socket.
477 /**
478 * This function is used to receive data on the sequenced packet socket. The
479 * function call will block until data has been received successfully, or
480 * until an error occurs.
481 *
482 * @param buffers One or more buffers into which the data will be received.
483 *
484 * @param out_flags After the receive call completes, contains flags
485 * associated with the received data. For example, if the
486 * socket_base::message_end_of_record bit is set then the received data marks
487 * the end of a record.
488 *
489 * @returns The number of bytes received.
490 *
491 * @throws boost::system::system_error Thrown on failure. An error code of
492 * boost::asio::error::eof indicates that the connection was closed by the
493 * peer.
494 *
495 * @par Example
496 * To receive into a single data buffer use the @ref buffer function as
497 * follows:
498 * @code
499 * socket.receive(boost::asio::buffer(data, size), out_flags);
500 * @endcode
501 * See the @ref buffer documentation for information on receiving into
502 * multiple buffers in one go, and how to use it with arrays, boost::array or
503 * std::vector.
504 */
505 template <typename MutableBufferSequence>
506 std::size_t receive(const MutableBufferSequence& buffers,
507 socket_base::message_flags& out_flags)
508 {
509 boost::system::error_code ec;
510 std::size_t s = this->impl_.get_service().receive_with_flags(
511 this->impl_.get_implementation(), buffers, 0, out_flags, ec);
512 boost::asio::detail::throw_error(err: ec, location: "receive");
513 return s;
514 }
515
516 /// Receive some data on the socket.
517 /**
518 * This function is used to receive data on the sequenced packet socket. The
519 * function call will block until data has been received successfully, or
520 * until an error occurs.
521 *
522 * @param buffers One or more buffers into which the data will be received.
523 *
524 * @param in_flags Flags specifying how the receive call is to be made.
525 *
526 * @param out_flags After the receive call completes, contains flags
527 * associated with the received data. For example, if the
528 * socket_base::message_end_of_record bit is set then the received data marks
529 * the end of a record.
530 *
531 * @returns The number of bytes received.
532 *
533 * @throws boost::system::system_error Thrown on failure. An error code of
534 * boost::asio::error::eof indicates that the connection was closed by the
535 * peer.
536 *
537 * @note The receive operation may not receive all of the requested number of
538 * bytes. Consider using the @ref read function if you need to ensure that the
539 * requested amount of data is read before the blocking operation completes.
540 *
541 * @par Example
542 * To receive into a single data buffer use the @ref buffer function as
543 * follows:
544 * @code
545 * socket.receive(boost::asio::buffer(data, size), 0, out_flags);
546 * @endcode
547 * See the @ref buffer documentation for information on receiving into
548 * multiple buffers in one go, and how to use it with arrays, boost::array or
549 * std::vector.
550 */
551 template <typename MutableBufferSequence>
552 std::size_t receive(const MutableBufferSequence& buffers,
553 socket_base::message_flags in_flags,
554 socket_base::message_flags& out_flags)
555 {
556 boost::system::error_code ec;
557 std::size_t s = this->impl_.get_service().receive_with_flags(
558 this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
559 boost::asio::detail::throw_error(err: ec, location: "receive");
560 return s;
561 }
562
563 /// Receive some data on a connected socket.
564 /**
565 * This function is used to receive data on the sequenced packet socket. The
566 * function call will block until data has been received successfully, or
567 * until an error occurs.
568 *
569 * @param buffers One or more buffers into which the data will be received.
570 *
571 * @param in_flags Flags specifying how the receive call is to be made.
572 *
573 * @param out_flags After the receive call completes, contains flags
574 * associated with the received data. For example, if the
575 * socket_base::message_end_of_record bit is set then the received data marks
576 * the end of a record.
577 *
578 * @param ec Set to indicate what error occurred, if any.
579 *
580 * @returns The number of bytes received. Returns 0 if an error occurred.
581 *
582 * @note The receive operation may not receive all of the requested number of
583 * bytes. Consider using the @ref read function if you need to ensure that the
584 * requested amount of data is read before the blocking operation completes.
585 */
586 template <typename MutableBufferSequence>
587 std::size_t receive(const MutableBufferSequence& buffers,
588 socket_base::message_flags in_flags,
589 socket_base::message_flags& out_flags, boost::system::error_code& ec)
590 {
591 return this->impl_.get_service().receive_with_flags(
592 this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
593 }
594
595 /// Start an asynchronous receive.
596 /**
597 * This function is used to asynchronously receive data from the sequenced
598 * packet socket. It is an initiating function for an @ref
599 * asynchronous_operation, and always returns immediately.
600 *
601 * @param buffers One or more buffers into which the data will be received.
602 * Although the buffers object may be copied as necessary, ownership of the
603 * underlying memory blocks is retained by the caller, which must guarantee
604 * that they remain valid until the completion handler is called.
605 *
606 * @param out_flags Once the asynchronous operation completes, contains flags
607 * associated with the received data. For example, if the
608 * socket_base::message_end_of_record bit is set then the received data marks
609 * the end of a record. The caller must guarantee that the referenced
610 * variable remains valid until the completion handler is called.
611 *
612 * @param token The @ref completion_token that will be used to produce a
613 * completion handler, which will be called when the receive completes.
614 * Potential completion tokens include @ref use_future, @ref use_awaitable,
615 * @ref yield_context, or a function object with the correct completion
616 * signature. The function signature of the completion handler must be:
617 * @code void handler(
618 * const boost::system::error_code& error, // Result of operation.
619 * std::size_t bytes_transferred // Number of bytes received.
620 * ); @endcode
621 * Regardless of whether the asynchronous operation completes immediately or
622 * not, the completion handler will not be invoked from within this function.
623 * On immediate completion, invocation of the handler will be performed in a
624 * manner equivalent to using boost::asio::post().
625 *
626 * @par Completion Signature
627 * @code void(boost::system::error_code, std::size_t) @endcode
628 *
629 * @par Example
630 * To receive into a single data buffer use the @ref buffer function as
631 * follows:
632 * @code
633 * socket.async_receive(boost::asio::buffer(data, size), out_flags, handler);
634 * @endcode
635 * See the @ref buffer documentation for information on receiving into
636 * multiple buffers in one go, and how to use it with arrays, boost::array or
637 * std::vector.
638 *
639 * @par Per-Operation Cancellation
640 * On POSIX or Windows operating systems, this asynchronous operation supports
641 * cancellation for the following boost::asio::cancellation_type values:
642 *
643 * @li @c cancellation_type::terminal
644 *
645 * @li @c cancellation_type::partial
646 *
647 * @li @c cancellation_type::total
648 */
649 template <typename MutableBufferSequence,
650 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
651 std::size_t)) ReadToken = default_completion_token_t<executor_type>>
652 auto async_receive(const MutableBufferSequence& buffers,
653 socket_base::message_flags& out_flags,
654 ReadToken&& token = default_completion_token_t<executor_type>())
655 -> decltype(
656 async_initiate<ReadToken,
657 void (boost::system::error_code, std::size_t)>(
658 declval<initiate_async_receive_with_flags>(), token,
659 buffers, socket_base::message_flags(0), &out_flags))
660 {
661 return async_initiate<ReadToken,
662 void (boost::system::error_code, std::size_t)>(
663 initiate_async_receive_with_flags(this), token,
664 buffers, socket_base::message_flags(0), &out_flags);
665 }
666
667 /// Start an asynchronous receive.
668 /**
669 * This function is used to asynchronously receive data from the sequenced
670 * data socket. It is an initiating function for an @ref
671 * asynchronous_operation, and always returns immediately.
672 *
673 * @param buffers One or more buffers into which the data will be received.
674 * Although the buffers object may be copied as necessary, ownership of the
675 * underlying memory blocks is retained by the caller, which must guarantee
676 * that they remain valid until the completion handler is called.
677 *
678 * @param in_flags Flags specifying how the receive call is to be made.
679 *
680 * @param out_flags Once the asynchronous operation completes, contains flags
681 * associated with the received data. For example, if the
682 * socket_base::message_end_of_record bit is set then the received data marks
683 * the end of a record. The caller must guarantee that the referenced
684 * variable remains valid until the completion handler is called.
685 *
686 * @param token The @ref completion_token that will be used to produce a
687 * completion handler, which will be called when the receive completes.
688 * Potential completion tokens include @ref use_future, @ref use_awaitable,
689 * @ref yield_context, or a function object with the correct completion
690 * signature. The function signature of the completion handler must be:
691 * @code void handler(
692 * const boost::system::error_code& error, // Result of operation.
693 * std::size_t bytes_transferred // Number of bytes received.
694 * ); @endcode
695 * Regardless of whether the asynchronous operation completes immediately or
696 * not, the completion handler will not be invoked from within this function.
697 * On immediate completion, invocation of the handler will be performed in a
698 * manner equivalent to using boost::asio::post().
699 *
700 * @par Completion Signature
701 * @code void(boost::system::error_code, std::size_t) @endcode
702 *
703 * @par Example
704 * To receive into a single data buffer use the @ref buffer function as
705 * follows:
706 * @code
707 * socket.async_receive(
708 * boost::asio::buffer(data, size),
709 * 0, out_flags, handler);
710 * @endcode
711 * See the @ref buffer documentation for information on receiving into
712 * multiple buffers in one go, and how to use it with arrays, boost::array or
713 * std::vector.
714 *
715 * @par Per-Operation Cancellation
716 * On POSIX or Windows operating systems, this asynchronous operation supports
717 * cancellation for the following boost::asio::cancellation_type values:
718 *
719 * @li @c cancellation_type::terminal
720 *
721 * @li @c cancellation_type::partial
722 *
723 * @li @c cancellation_type::total
724 */
725 template <typename MutableBufferSequence,
726 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
727 std::size_t)) ReadToken = default_completion_token_t<executor_type>>
728 auto async_receive(const MutableBufferSequence& buffers,
729 socket_base::message_flags in_flags,
730 socket_base::message_flags& out_flags,
731 ReadToken&& token = default_completion_token_t<executor_type>())
732 -> decltype(
733 async_initiate<ReadToken,
734 void (boost::system::error_code, std::size_t)>(
735 declval<initiate_async_receive_with_flags>(),
736 token, buffers, in_flags, &out_flags))
737 {
738 return async_initiate<ReadToken,
739 void (boost::system::error_code, std::size_t)>(
740 initiate_async_receive_with_flags(this),
741 token, buffers, in_flags, &out_flags);
742 }
743
744private:
745 // Disallow copying and assignment.
746 basic_seq_packet_socket(const basic_seq_packet_socket&) = delete;
747 basic_seq_packet_socket& operator=(
748 const basic_seq_packet_socket&) = delete;
749
750 class initiate_async_send
751 {
752 public:
753 typedef Executor executor_type;
754
755 explicit initiate_async_send(basic_seq_packet_socket* self)
756 : self_(self)
757 {
758 }
759
760 const executor_type& get_executor() const noexcept
761 {
762 return self_->get_executor();
763 }
764
765 template <typename WriteHandler, typename ConstBufferSequence>
766 void operator()(WriteHandler&& handler,
767 const ConstBufferSequence& buffers,
768 socket_base::message_flags flags) const
769 {
770 // If you get an error on the following line it means that your handler
771 // does not meet the documented type requirements for a WriteHandler.
772 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
773
774 detail::non_const_lvalue<WriteHandler> handler2(handler);
775 self_->impl_.get_service().async_send(
776 self_->impl_.get_implementation(), buffers, flags,
777 handler2.value, self_->impl_.get_executor());
778 }
779
780 private:
781 basic_seq_packet_socket* self_;
782 };
783
784 class initiate_async_receive_with_flags
785 {
786 public:
787 typedef Executor executor_type;
788
789 explicit initiate_async_receive_with_flags(basic_seq_packet_socket* self)
790 : self_(self)
791 {
792 }
793
794 const executor_type& get_executor() const noexcept
795 {
796 return self_->get_executor();
797 }
798
799 template <typename ReadHandler, typename MutableBufferSequence>
800 void operator()(ReadHandler&& handler,
801 const MutableBufferSequence& buffers,
802 socket_base::message_flags in_flags,
803 socket_base::message_flags* out_flags) const
804 {
805 // If you get an error on the following line it means that your handler
806 // does not meet the documented type requirements for a ReadHandler.
807 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
808
809 detail::non_const_lvalue<ReadHandler> handler2(handler);
810 self_->impl_.get_service().async_receive_with_flags(
811 self_->impl_.get_implementation(), buffers, in_flags,
812 *out_flags, handler2.value, self_->impl_.get_executor());
813 }
814
815 private:
816 basic_seq_packet_socket* self_;
817 };
818};
819
820} // namespace asio
821} // namespace boost
822
823#include <boost/asio/detail/pop_options.hpp>
824
825#endif // BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
826

source code of boost/libs/asio/include/boost/asio/basic_seq_packet_socket.hpp