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 
28 namespace boost {
29 namespace 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  */
40 template <typename Protocol,
41     typename SeqPacketSocketService = seq_packet_socket_service<Protocol> >
42 class basic_seq_packet_socket
43   : public basic_socket<Protocol, SeqPacketSocketService>
44 {
45 public:
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    */
basic_seq_packet_socket(boost::asio::io_service & io_service)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    */
basic_seq_packet_socket(boost::asio::io_service & io_service,const protocol_type & protocol)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    */
basic_seq_packet_socket(boost::asio::io_service & io_service,const endpoint_type & endpoint)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    */
basic_seq_packet_socket(boost::asio::io_service & io_service,const protocol_type & protocol,const native_handle_type & native_socket)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    */
basic_seq_packet_socket(basic_seq_packet_socket && other)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    */
operator =(basic_seq_packet_socket && other)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>
basic_seq_packet_socket(basic_seq_packet_socket<Protocol1,SeqPacketSocketService1> && other,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)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,
operator =(basic_seq_packet_socket<Protocol1,SeqPacketSocketService1> && other)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>
send(const ConstBufferSequence & buffers,socket_base::message_flags flags)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>
send(const ConstBufferSequence & buffers,socket_base::message_flags flags,boost::system::error_code & ec)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>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))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>
receive(const MutableBufferSequence & buffers,socket_base::message_flags & out_flags)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>
receive(const MutableBufferSequence & buffers,socket_base::message_flags in_flags,socket_base::message_flags & out_flags)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>
receive(const MutableBufferSequence & buffers,socket_base::message_flags in_flags,socket_base::message_flags & out_flags,boost::system::error_code & ec)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>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))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>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))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