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 | |
27 | namespace boost { |
28 | namespace 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. |
34 | template <typename Protocol, typename Executor = any_io_executor> |
35 | class 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 | */ |
55 | template <typename Protocol, typename Executor> |
56 | class basic_seq_packet_socket |
57 | : public basic_socket<Protocol, Executor> |
58 | { |
59 | private: |
60 | class initiate_async_send; |
61 | class initiate_async_receive_with_flags; |
62 | |
63 | public: |
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 | |
744 | private: |
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 | |