1//
2// basic_seq_packet_socket.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 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#include <boost/asio/seq_packet_socket_service.hpp>
25
26#include <boost/asio/detail/push_options.hpp>
27
28namespace boost {
29namespace asio {
30
31/// Provides sequenced packet socket functionality.
32/**
33 * The basic_seq_packet_socket class template provides asynchronous and blocking
34 * sequenced packet socket functionality.
35 *
36 * @par Thread Safety
37 * @e Distinct @e objects: Safe.@n
38 * @e Shared @e objects: Unsafe.
39 */
40template <typename Protocol,
41 typename SeqPacketSocketService = seq_packet_socket_service<Protocol> >
42class basic_seq_packet_socket
43 : public basic_socket<Protocol, SeqPacketSocketService>
44{
45public:
46 /// (Deprecated: Use native_handle_type.) The native representation of a
47 /// socket.
48 typedef typename SeqPacketSocketService::native_handle_type native_type;
49
50 /// The native representation of a socket.
51 typedef typename SeqPacketSocketService::native_handle_type
52 native_handle_type;
53
54 /// The protocol type.
55 typedef Protocol protocol_type;
56
57 /// The endpoint type.
58 typedef typename Protocol::endpoint endpoint_type;
59
60 /// Construct a basic_seq_packet_socket without opening it.
61 /**
62 * This constructor creates a sequenced packet socket without opening it. The
63 * socket needs to be opened and then connected or accepted before data can
64 * be sent or received on it.
65 *
66 * @param io_service The io_service object that the sequenced packet socket
67 * will use to dispatch handlers for any asynchronous operations performed on
68 * the socket.
69 */
70 explicit basic_seq_packet_socket(boost::asio::io_service& io_service)
71 : basic_socket<Protocol, SeqPacketSocketService>(io_service)
72 {
73 }
74
75 /// Construct and open a basic_seq_packet_socket.
76 /**
77 * This constructor creates and opens a sequenced_packet socket. The socket
78 * needs to be connected or accepted before data can be sent or received on
79 * it.
80 *
81 * @param io_service The io_service object that the sequenced packet socket
82 * will use to dispatch handlers for any asynchronous operations performed on
83 * the socket.
84 *
85 * @param protocol An object specifying protocol parameters to be used.
86 *
87 * @throws boost::system::system_error Thrown on failure.
88 */
89 basic_seq_packet_socket(boost::asio::io_service& io_service,
90 const protocol_type& protocol)
91 : basic_socket<Protocol, SeqPacketSocketService>(io_service, protocol)
92 {
93 }
94
95 /// Construct a basic_seq_packet_socket, opening it and binding it to the
96 /// given local endpoint.
97 /**
98 * This constructor creates a sequenced packet socket and automatically opens
99 * it bound to the specified endpoint on the local machine. The protocol used
100 * is the protocol associated with the given endpoint.
101 *
102 * @param io_service The io_service object that the sequenced packet socket
103 * will use to dispatch handlers for any asynchronous operations performed on
104 * the socket.
105 *
106 * @param endpoint An endpoint on the local machine to which the sequenced
107 * packet socket will be bound.
108 *
109 * @throws boost::system::system_error Thrown on failure.
110 */
111 basic_seq_packet_socket(boost::asio::io_service& io_service,
112 const endpoint_type& endpoint)
113 : basic_socket<Protocol, SeqPacketSocketService>(io_service, endpoint)
114 {
115 }
116
117 /// Construct a basic_seq_packet_socket on an existing native socket.
118 /**
119 * This constructor creates a sequenced packet socket object to hold an
120 * existing native socket.
121 *
122 * @param io_service The io_service object that the sequenced packet socket
123 * will use to dispatch handlers for any asynchronous operations performed on
124 * the socket.
125 *
126 * @param protocol An object specifying protocol parameters to be used.
127 *
128 * @param native_socket The new underlying socket implementation.
129 *
130 * @throws boost::system::system_error Thrown on failure.
131 */
132 basic_seq_packet_socket(boost::asio::io_service& io_service,
133 const protocol_type& protocol, const native_handle_type& native_socket)
134 : basic_socket<Protocol, SeqPacketSocketService>(
135 io_service, protocol, native_socket)
136 {
137 }
138
139#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
140 /// Move-construct a basic_seq_packet_socket from another.
141 /**
142 * This constructor moves a sequenced packet socket from one object to
143 * another.
144 *
145 * @param other The other basic_seq_packet_socket object from which the move
146 * will occur.
147 *
148 * @note Following the move, the moved-from object is in the same state as if
149 * constructed using the @c basic_seq_packet_socket(io_service&) constructor.
150 */
151 basic_seq_packet_socket(basic_seq_packet_socket&& other)
152 : basic_socket<Protocol, SeqPacketSocketService>(
153 BOOST_ASIO_MOVE_CAST(basic_seq_packet_socket)(other))
154 {
155 }
156
157 /// Move-assign a basic_seq_packet_socket from another.
158 /**
159 * This assignment operator moves a sequenced packet socket from one object to
160 * another.
161 *
162 * @param other The other basic_seq_packet_socket object from which the move
163 * will occur.
164 *
165 * @note Following the move, the moved-from object is in the same state as if
166 * constructed using the @c basic_seq_packet_socket(io_service&) constructor.
167 */
168 basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
169 {
170 basic_socket<Protocol, SeqPacketSocketService>::operator=(
171 BOOST_ASIO_MOVE_CAST(basic_seq_packet_socket)(other));
172 return *this;
173 }
174
175 /// Move-construct a basic_seq_packet_socket from a socket of another protocol
176 /// type.
177 /**
178 * This constructor moves a sequenced packet socket from one object to
179 * another.
180 *
181 * @param other The other basic_seq_packet_socket object from which the move
182 * will occur.
183 *
184 * @note Following the move, the moved-from object is in the same state as if
185 * constructed using the @c basic_seq_packet_socket(io_service&) constructor.
186 */
187 template <typename Protocol1, typename SeqPacketSocketService1>
188 basic_seq_packet_socket(
189 basic_seq_packet_socket<Protocol1, SeqPacketSocketService1>&& other,
190 typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
191 : basic_socket<Protocol, SeqPacketSocketService>(
192 BOOST_ASIO_MOVE_CAST2(basic_seq_packet_socket<
193 Protocol1, SeqPacketSocketService1>)(other))
194 {
195 }
196
197 /// Move-assign a basic_seq_packet_socket from a socket of another protocol
198 /// type.
199 /**
200 * This assignment operator moves a sequenced packet socket from one object to
201 * another.
202 *
203 * @param other The other basic_seq_packet_socket object from which the move
204 * will occur.
205 *
206 * @note Following the move, the moved-from object is in the same state as if
207 * constructed using the @c basic_seq_packet_socket(io_service&) constructor.
208 */
209 template <typename Protocol1, typename SeqPacketSocketService1>
210 typename enable_if<is_convertible<Protocol1, Protocol>::value,
211 basic_seq_packet_socket>::type& operator=(
212 basic_seq_packet_socket<Protocol1, SeqPacketSocketService1>&& other)
213 {
214 basic_socket<Protocol, SeqPacketSocketService>::operator=(
215 BOOST_ASIO_MOVE_CAST2(basic_seq_packet_socket<
216 Protocol1, SeqPacketSocketService1>)(other));
217 return *this;
218 }
219#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
220
221 /// Send some data on the socket.
222 /**
223 * This function is used to send data on the sequenced packet socket. The
224 * function call will block until the data has been sent successfully, or an
225 * until error occurs.
226 *
227 * @param buffers One or more data buffers to be sent on the socket.
228 *
229 * @param flags Flags specifying how the send call is to be made.
230 *
231 * @returns The number of bytes sent.
232 *
233 * @throws boost::system::system_error Thrown on failure.
234 *
235 * @par Example
236 * To send a single data buffer use the @ref buffer function as follows:
237 * @code
238 * socket.send(boost::asio::buffer(data, size), 0);
239 * @endcode
240 * See the @ref buffer documentation for information on sending multiple
241 * buffers in one go, and how to use it with arrays, boost::array or
242 * std::vector.
243 */
244 template <typename ConstBufferSequence>
245 std::size_t send(const ConstBufferSequence& buffers,
246 socket_base::message_flags flags)
247 {
248 boost::system::error_code ec;
249 std::size_t s = this->get_service().send(
250 this->get_implementation(), buffers, flags, ec);
251 boost::asio::detail::throw_error(ec, "send");
252 return s;
253 }
254
255 /// Send some data on the socket.
256 /**
257 * This function is used to send data on the sequenced packet socket. The
258 * function call will block the data has been sent successfully, or an until
259 * error occurs.
260 *
261 * @param buffers One or more data buffers to be sent on the socket.
262 *
263 * @param flags Flags specifying how the send call is to be made.
264 *
265 * @param ec Set to indicate what error occurred, if any.
266 *
267 * @returns The number of bytes sent. Returns 0 if an error occurred.
268 *
269 * @note The send operation may not transmit all of the data to the peer.
270 * Consider using the @ref write function if you need to ensure that all data
271 * is written before the blocking operation completes.
272 */
273 template <typename ConstBufferSequence>
274 std::size_t send(const ConstBufferSequence& buffers,
275 socket_base::message_flags flags, boost::system::error_code& ec)
276 {
277 return this->get_service().send(
278 this->get_implementation(), buffers, flags, ec);
279 }
280
281 /// Start an asynchronous send.
282 /**
283 * This function is used to asynchronously send data on the sequenced packet
284 * socket. The function call always returns immediately.
285 *
286 * @param buffers One or more data buffers to be sent on the socket. Although
287 * the buffers object may be copied as necessary, ownership of the underlying
288 * memory blocks is retained by the caller, which must guarantee that they
289 * remain valid until the handler is called.
290 *
291 * @param flags Flags specifying how the send call is to be made.
292 *
293 * @param handler The handler to be called when the send operation completes.
294 * Copies will be made of the handler as required. The function signature of
295 * the handler must be:
296 * @code void handler(
297 * const boost::system::error_code& error, // Result of operation.
298 * std::size_t bytes_transferred // Number of bytes sent.
299 * ); @endcode
300 * Regardless of whether the asynchronous operation completes immediately or
301 * not, the handler will not be invoked from within this function. Invocation
302 * of the handler will be performed in a manner equivalent to using
303 * boost::asio::io_service::post().
304 *
305 * @par Example
306 * To send a single data buffer use the @ref buffer function as follows:
307 * @code
308 * socket.async_send(boost::asio::buffer(data, size), 0, handler);
309 * @endcode
310 * See the @ref buffer documentation for information on sending multiple
311 * buffers in one go, and how to use it with arrays, boost::array or
312 * std::vector.
313 */
314 template <typename ConstBufferSequence, typename WriteHandler>
315 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
316 void (boost::system::error_code, std::size_t))
317 async_send(const ConstBufferSequence& buffers,
318 socket_base::message_flags flags,
319 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
320 {
321 // If you get an error on the following line it means that your handler does
322 // not meet the documented type requirements for a WriteHandler.
323 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
324
325 return this->get_service().async_send(this->get_implementation(),
326 buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
327 }
328
329 /// Receive some data on the socket.
330 /**
331 * This function is used to receive data on the sequenced packet socket. The
332 * function call will block until data has been received successfully, or
333 * until an error occurs.
334 *
335 * @param buffers One or more buffers into which the data will be received.
336 *
337 * @param out_flags After the receive call completes, contains flags
338 * associated with the received data. For example, if the
339 * socket_base::message_end_of_record bit is set then the received data marks
340 * the end of a record.
341 *
342 * @returns The number of bytes received.
343 *
344 * @throws boost::system::system_error Thrown on failure. An error code of
345 * boost::asio::error::eof indicates that the connection was closed by the
346 * peer.
347 *
348 * @par Example
349 * To receive into a single data buffer use the @ref buffer function as
350 * follows:
351 * @code
352 * socket.receive(boost::asio::buffer(data, size), out_flags);
353 * @endcode
354 * See the @ref buffer documentation for information on receiving into
355 * multiple buffers in one go, and how to use it with arrays, boost::array or
356 * std::vector.
357 */
358 template <typename MutableBufferSequence>
359 std::size_t receive(const MutableBufferSequence& buffers,
360 socket_base::message_flags& out_flags)
361 {
362 boost::system::error_code ec;
363 std::size_t s = this->get_service().receive(
364 this->get_implementation(), buffers, 0, out_flags, ec);
365 boost::asio::detail::throw_error(ec, "receive");
366 return s;
367 }
368
369 /// Receive some data on the socket.
370 /**
371 * This function is used to receive data on the sequenced packet socket. The
372 * function call will block until data has been received successfully, or
373 * until an error occurs.
374 *
375 * @param buffers One or more buffers into which the data will be received.
376 *
377 * @param in_flags Flags specifying how the receive call is to be made.
378 *
379 * @param out_flags After the receive call completes, contains flags
380 * associated with the received data. For example, if the
381 * socket_base::message_end_of_record bit is set then the received data marks
382 * the end of a record.
383 *
384 * @returns The number of bytes received.
385 *
386 * @throws boost::system::system_error Thrown on failure. An error code of
387 * boost::asio::error::eof indicates that the connection was closed by the
388 * peer.
389 *
390 * @note The receive operation may not receive all of the requested number of
391 * bytes. Consider using the @ref read function if you need to ensure that the
392 * requested amount of data is read before the blocking operation completes.
393 *
394 * @par Example
395 * To receive into a single data buffer use the @ref buffer function as
396 * follows:
397 * @code
398 * socket.receive(boost::asio::buffer(data, size), 0, out_flags);
399 * @endcode
400 * See the @ref buffer documentation for information on receiving into
401 * multiple buffers in one go, and how to use it with arrays, boost::array or
402 * std::vector.
403 */
404 template <typename MutableBufferSequence>
405 std::size_t receive(const MutableBufferSequence& buffers,
406 socket_base::message_flags in_flags,
407 socket_base::message_flags& out_flags)
408 {
409 boost::system::error_code ec;
410 std::size_t s = this->get_service().receive(
411 this->get_implementation(), buffers, in_flags, out_flags, ec);
412 boost::asio::detail::throw_error(ec, "receive");
413 return s;
414 }
415
416 /// Receive some data on a connected socket.
417 /**
418 * This function is used to receive data on the sequenced packet socket. The
419 * function call will block until data has been received successfully, or
420 * until an error occurs.
421 *
422 * @param buffers One or more buffers into which the data will be received.
423 *
424 * @param in_flags Flags specifying how the receive call is to be made.
425 *
426 * @param out_flags After the receive call completes, contains flags
427 * associated with the received data. For example, if the
428 * socket_base::message_end_of_record bit is set then the received data marks
429 * the end of a record.
430 *
431 * @param ec Set to indicate what error occurred, if any.
432 *
433 * @returns The number of bytes received. Returns 0 if an error occurred.
434 *
435 * @note The receive operation may not receive all of the requested number of
436 * bytes. Consider using the @ref read function if you need to ensure that the
437 * requested amount of data is read before the blocking operation completes.
438 */
439 template <typename MutableBufferSequence>
440 std::size_t receive(const MutableBufferSequence& buffers,
441 socket_base::message_flags in_flags,
442 socket_base::message_flags& out_flags, boost::system::error_code& ec)
443 {
444 return this->get_service().receive(this->get_implementation(),
445 buffers, in_flags, out_flags, ec);
446 }
447
448 /// Start an asynchronous receive.
449 /**
450 * This function is used to asynchronously receive data from the sequenced
451 * packet socket. The function call always returns immediately.
452 *
453 * @param buffers One or more buffers into which the data will be received.
454 * Although the buffers object may be copied as necessary, ownership of the
455 * underlying memory blocks is retained by the caller, which must guarantee
456 * that they remain valid until the handler is called.
457 *
458 * @param out_flags Once the asynchronous operation completes, contains flags
459 * associated with the received data. For example, if the
460 * socket_base::message_end_of_record bit is set then the received data marks
461 * the end of a record. The caller must guarantee that the referenced
462 * variable remains valid until the handler is called.
463 *
464 * @param handler The handler to be called when the receive operation
465 * completes. Copies will be made of the handler as required. The function
466 * signature of the handler must be:
467 * @code void handler(
468 * const boost::system::error_code& error, // Result of operation.
469 * std::size_t bytes_transferred // Number of bytes received.
470 * ); @endcode
471 * Regardless of whether the asynchronous operation completes immediately or
472 * not, the handler will not be invoked from within this function. Invocation
473 * of the handler will be performed in a manner equivalent to using
474 * boost::asio::io_service::post().
475 *
476 * @par Example
477 * To receive into a single data buffer use the @ref buffer function as
478 * follows:
479 * @code
480 * socket.async_receive(boost::asio::buffer(data, size), out_flags, handler);
481 * @endcode
482 * See the @ref buffer documentation for information on receiving into
483 * multiple buffers in one go, and how to use it with arrays, boost::array or
484 * std::vector.
485 */
486 template <typename MutableBufferSequence, typename ReadHandler>
487 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
488 void (boost::system::error_code, std::size_t))
489 async_receive(const MutableBufferSequence& buffers,
490 socket_base::message_flags& out_flags,
491 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
492 {
493 // If you get an error on the following line it means that your handler does
494 // not meet the documented type requirements for a ReadHandler.
495 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
496
497 return this->get_service().async_receive(
498 this->get_implementation(), buffers, 0, out_flags,
499 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
500 }
501
502 /// Start an asynchronous receive.
503 /**
504 * This function is used to asynchronously receive data from the sequenced
505 * data socket. The function call always returns immediately.
506 *
507 * @param buffers One or more buffers into which the data will be received.
508 * Although the buffers object may be copied as necessary, ownership of the
509 * underlying memory blocks is retained by the caller, which must guarantee
510 * that they remain valid until the handler is called.
511 *
512 * @param in_flags Flags specifying how the receive call is to be made.
513 *
514 * @param out_flags Once the asynchronous operation completes, contains flags
515 * associated with the received data. For example, if the
516 * socket_base::message_end_of_record bit is set then the received data marks
517 * the end of a record. The caller must guarantee that the referenced
518 * variable remains valid until the handler is called.
519 *
520 * @param handler The handler to be called when the receive operation
521 * completes. Copies will be made of the handler as required. The function
522 * signature of the handler must be:
523 * @code void handler(
524 * const boost::system::error_code& error, // Result of operation.
525 * std::size_t bytes_transferred // Number of bytes received.
526 * ); @endcode
527 * Regardless of whether the asynchronous operation completes immediately or
528 * not, the handler will not be invoked from within this function. Invocation
529 * of the handler will be performed in a manner equivalent to using
530 * boost::asio::io_service::post().
531 *
532 * @par Example
533 * To receive into a single data buffer use the @ref buffer function as
534 * follows:
535 * @code
536 * socket.async_receive(
537 * boost::asio::buffer(data, size),
538 * 0, out_flags, handler);
539 * @endcode
540 * See the @ref buffer documentation for information on receiving into
541 * multiple buffers in one go, and how to use it with arrays, boost::array or
542 * std::vector.
543 */
544 template <typename MutableBufferSequence, typename ReadHandler>
545 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
546 void (boost::system::error_code, std::size_t))
547 async_receive(const MutableBufferSequence& buffers,
548 socket_base::message_flags in_flags,
549 socket_base::message_flags& out_flags,
550 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
551 {
552 // If you get an error on the following line it means that your handler does
553 // not meet the documented type requirements for a ReadHandler.
554 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
555
556 return this->get_service().async_receive(
557 this->get_implementation(), buffers, in_flags, out_flags,
558 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
559 }
560};
561
562} // namespace asio
563} // namespace boost
564
565#include <boost/asio/detail/pop_options.hpp>
566
567#endif // BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
568