1 //
2 // basic_socket_acceptor.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2016 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 ASIO_BASIC_SOCKET_ACCEPTOR_HPP
12 #define ASIO_BASIC_SOCKET_ACCEPTOR_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include "asio/detail/config.hpp"
19 #include "asio/basic_io_object.hpp"
20 #include "asio/basic_socket.hpp"
21 #include "asio/detail/handler_type_requirements.hpp"
22 #include "asio/detail/throw_error.hpp"
23 #include "asio/detail/type_traits.hpp"
24 #include "asio/error.hpp"
25 #include "asio/socket_acceptor_service.hpp"
26 #include "asio/socket_base.hpp"
27 
28 #include "asio/detail/push_options.hpp"
29 
30 namespace asio {
31 
32 /// Provides the ability to accept new connections.
33 /**
34  * The basic_socket_acceptor class template is used for accepting new socket
35  * connections.
36  *
37  * @par Thread Safety
38  * @e Distinct @e objects: Safe.@n
39  * @e Shared @e objects: Unsafe.
40  *
41  * @par Example
42  * Opening a socket acceptor with the SO_REUSEADDR option enabled:
43  * @code
44  * asio::ip::tcp::acceptor acceptor(io_service);
45  * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port);
46  * acceptor.open(endpoint.protocol());
47  * acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
48  * acceptor.bind(endpoint);
49  * acceptor.listen();
50  * @endcode
51  */
52 template <typename Protocol,
53     typename SocketAcceptorService = socket_acceptor_service<Protocol> >
54 class basic_socket_acceptor
55   : public basic_io_object<SocketAcceptorService>,
56     public socket_base
57 {
58 public:
59   /// (Deprecated: Use native_handle_type.) The native representation of an
60   /// acceptor.
61   typedef typename SocketAcceptorService::native_handle_type native_type;
62 
63   /// The native representation of an acceptor.
64   typedef typename SocketAcceptorService::native_handle_type native_handle_type;
65 
66   /// The protocol type.
67   typedef Protocol protocol_type;
68 
69   /// The endpoint type.
70   typedef typename Protocol::endpoint endpoint_type;
71 
72   /// Construct an acceptor without opening it.
73   /**
74    * This constructor creates an acceptor without opening it to listen for new
75    * connections. The open() function must be called before the acceptor can
76    * accept new socket connections.
77    *
78    * @param io_service The io_service object that the acceptor will use to
79    * dispatch handlers for any asynchronous operations performed on the
80    * acceptor.
81    */
basic_socket_acceptor(asio::io_service & io_service)82   explicit basic_socket_acceptor(asio::io_service& io_service)
83     : basic_io_object<SocketAcceptorService>(io_service)
84   {
85   }
86 
87   /// Construct an open acceptor.
88   /**
89    * This constructor creates an acceptor and automatically opens it.
90    *
91    * @param io_service The io_service object that the acceptor will use to
92    * dispatch handlers for any asynchronous operations performed on the
93    * acceptor.
94    *
95    * @param protocol An object specifying protocol parameters to be used.
96    *
97    * @throws asio::system_error Thrown on failure.
98    */
basic_socket_acceptor(asio::io_service & io_service,const protocol_type & protocol)99   basic_socket_acceptor(asio::io_service& io_service,
100       const protocol_type& protocol)
101     : basic_io_object<SocketAcceptorService>(io_service)
102   {
103     asio::error_code ec;
104     this->get_service().open(this->get_implementation(), protocol, ec);
105     asio::detail::throw_error(ec, "open");
106   }
107 
108   /// Construct an acceptor opened on the given endpoint.
109   /**
110    * This constructor creates an acceptor and automatically opens it to listen
111    * for new connections on the specified endpoint.
112    *
113    * @param io_service The io_service object that the acceptor will use to
114    * dispatch handlers for any asynchronous operations performed on the
115    * acceptor.
116    *
117    * @param endpoint An endpoint on the local machine on which the acceptor
118    * will listen for new connections.
119    *
120    * @param reuse_addr Whether the constructor should set the socket option
121    * socket_base::reuse_address.
122    *
123    * @throws asio::system_error Thrown on failure.
124    *
125    * @note This constructor is equivalent to the following code:
126    * @code
127    * basic_socket_acceptor<Protocol> acceptor(io_service);
128    * acceptor.open(endpoint.protocol());
129    * if (reuse_addr)
130    *   acceptor.set_option(socket_base::reuse_address(true));
131    * acceptor.bind(endpoint);
132    * acceptor.listen(listen_backlog);
133    * @endcode
134    */
basic_socket_acceptor(asio::io_service & io_service,const endpoint_type & endpoint,bool reuse_addr=true)135   basic_socket_acceptor(asio::io_service& io_service,
136       const endpoint_type& endpoint, bool reuse_addr = true)
137     : basic_io_object<SocketAcceptorService>(io_service)
138   {
139     asio::error_code ec;
140     const protocol_type protocol = endpoint.protocol();
141     this->get_service().open(this->get_implementation(), protocol, ec);
142     asio::detail::throw_error(ec, "open");
143     if (reuse_addr)
144     {
145       this->get_service().set_option(this->get_implementation(),
146           socket_base::reuse_address(true), ec);
147       asio::detail::throw_error(ec, "set_option");
148     }
149     this->get_service().bind(this->get_implementation(), endpoint, ec);
150     asio::detail::throw_error(ec, "bind");
151     this->get_service().listen(this->get_implementation(),
152         socket_base::max_connections, ec);
153     asio::detail::throw_error(ec, "listen");
154   }
155 
156   /// Construct a basic_socket_acceptor on an existing native acceptor.
157   /**
158    * This constructor creates an acceptor object to hold an existing native
159    * acceptor.
160    *
161    * @param io_service The io_service object that the acceptor will use to
162    * dispatch handlers for any asynchronous operations performed on the
163    * acceptor.
164    *
165    * @param protocol An object specifying protocol parameters to be used.
166    *
167    * @param native_acceptor A native acceptor.
168    *
169    * @throws asio::system_error Thrown on failure.
170    */
basic_socket_acceptor(asio::io_service & io_service,const protocol_type & protocol,const native_handle_type & native_acceptor)171   basic_socket_acceptor(asio::io_service& io_service,
172       const protocol_type& protocol, const native_handle_type& native_acceptor)
173     : basic_io_object<SocketAcceptorService>(io_service)
174   {
175     asio::error_code ec;
176     this->get_service().assign(this->get_implementation(),
177         protocol, native_acceptor, ec);
178     asio::detail::throw_error(ec, "assign");
179   }
180 
181 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
182   /// Move-construct a basic_socket_acceptor from another.
183   /**
184    * This constructor moves an acceptor from one object to another.
185    *
186    * @param other The other basic_socket_acceptor object from which the move
187    * will occur.
188    *
189    * @note Following the move, the moved-from object is in the same state as if
190    * constructed using the @c basic_socket_acceptor(io_service&) constructor.
191    */
basic_socket_acceptor(basic_socket_acceptor && other)192   basic_socket_acceptor(basic_socket_acceptor&& other)
193     : basic_io_object<SocketAcceptorService>(
194         ASIO_MOVE_CAST(basic_socket_acceptor)(other))
195   {
196   }
197 
198   /// Move-assign a basic_socket_acceptor from another.
199   /**
200    * This assignment operator moves an acceptor from one object to another.
201    *
202    * @param other The other basic_socket_acceptor object from which the move
203    * will occur.
204    *
205    * @note Following the move, the moved-from object is in the same state as if
206    * constructed using the @c basic_socket_acceptor(io_service&) constructor.
207    */
operator =(basic_socket_acceptor && other)208   basic_socket_acceptor& operator=(basic_socket_acceptor&& other)
209   {
210     basic_io_object<SocketAcceptorService>::operator=(
211         ASIO_MOVE_CAST(basic_socket_acceptor)(other));
212     return *this;
213   }
214 
215   // All socket acceptors have access to each other's implementations.
216   template <typename Protocol1, typename SocketAcceptorService1>
217   friend class basic_socket_acceptor;
218 
219   /// Move-construct a basic_socket_acceptor from an acceptor of another
220   /// protocol type.
221   /**
222    * This constructor moves an acceptor from one object to another.
223    *
224    * @param other The other basic_socket_acceptor object from which the move
225    * will occur.
226    *
227    * @note Following the move, the moved-from object is in the same state as if
228    * constructed using the @c basic_socket(io_service&) constructor.
229    */
230   template <typename Protocol1, typename SocketAcceptorService1>
basic_socket_acceptor(basic_socket_acceptor<Protocol1,SocketAcceptorService1> && other,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)231   basic_socket_acceptor(
232       basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other,
233       typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
234     : basic_io_object<SocketAcceptorService>(other.get_io_service())
235   {
236     this->get_service().template converting_move_construct<Protocol1>(
237         this->get_implementation(), other.get_implementation());
238   }
239 
240   /// Move-assign a basic_socket_acceptor from an acceptor of another protocol
241   /// type.
242   /**
243    * This assignment operator moves an acceptor from one object to another.
244    *
245    * @param other The other basic_socket_acceptor object from which the move
246    * will occur.
247    *
248    * @note Following the move, the moved-from object is in the same state as if
249    * constructed using the @c basic_socket(io_service&) constructor.
250    */
251   template <typename Protocol1, typename SocketAcceptorService1>
252   typename enable_if<is_convertible<Protocol1, Protocol>::value,
operator =(basic_socket_acceptor<Protocol1,SocketAcceptorService1> && other)253       basic_socket_acceptor>::type& operator=(
254         basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other)
255   {
256     basic_socket_acceptor tmp(ASIO_MOVE_CAST2(basic_socket_acceptor<
257             Protocol1, SocketAcceptorService1>)(other));
258     basic_io_object<SocketAcceptorService>::operator=(
259         ASIO_MOVE_CAST(basic_socket_acceptor)(tmp));
260     return *this;
261   }
262 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
263 
264   /// Open the acceptor using the specified protocol.
265   /**
266    * This function opens the socket acceptor so that it will use the specified
267    * protocol.
268    *
269    * @param protocol An object specifying which protocol is to be used.
270    *
271    * @throws asio::system_error Thrown on failure.
272    *
273    * @par Example
274    * @code
275    * asio::ip::tcp::acceptor acceptor(io_service);
276    * acceptor.open(asio::ip::tcp::v4());
277    * @endcode
278    */
open(const protocol_type & protocol=protocol_type ())279   void open(const protocol_type& protocol = protocol_type())
280   {
281     asio::error_code ec;
282     this->get_service().open(this->get_implementation(), protocol, ec);
283     asio::detail::throw_error(ec, "open");
284   }
285 
286   /// Open the acceptor using the specified protocol.
287   /**
288    * This function opens the socket acceptor so that it will use the specified
289    * protocol.
290    *
291    * @param protocol An object specifying which protocol is to be used.
292    *
293    * @param ec Set to indicate what error occurred, if any.
294    *
295    * @par Example
296    * @code
297    * asio::ip::tcp::acceptor acceptor(io_service);
298    * asio::error_code ec;
299    * acceptor.open(asio::ip::tcp::v4(), ec);
300    * if (ec)
301    * {
302    *   // An error occurred.
303    * }
304    * @endcode
305    */
open(const protocol_type & protocol,asio::error_code & ec)306   asio::error_code open(const protocol_type& protocol,
307       asio::error_code& ec)
308   {
309     return this->get_service().open(this->get_implementation(), protocol, ec);
310   }
311 
312   /// Assigns an existing native acceptor to the acceptor.
313   /*
314    * This function opens the acceptor to hold an existing native acceptor.
315    *
316    * @param protocol An object specifying which protocol is to be used.
317    *
318    * @param native_acceptor A native acceptor.
319    *
320    * @throws asio::system_error Thrown on failure.
321    */
assign(const protocol_type & protocol,const native_handle_type & native_acceptor)322   void assign(const protocol_type& protocol,
323       const native_handle_type& native_acceptor)
324   {
325     asio::error_code ec;
326     this->get_service().assign(this->get_implementation(),
327         protocol, native_acceptor, ec);
328     asio::detail::throw_error(ec, "assign");
329   }
330 
331   /// Assigns an existing native acceptor to the acceptor.
332   /*
333    * This function opens the acceptor to hold an existing native acceptor.
334    *
335    * @param protocol An object specifying which protocol is to be used.
336    *
337    * @param native_acceptor A native acceptor.
338    *
339    * @param ec Set to indicate what error occurred, if any.
340    */
assign(const protocol_type & protocol,const native_handle_type & native_acceptor,asio::error_code & ec)341   asio::error_code assign(const protocol_type& protocol,
342       const native_handle_type& native_acceptor, asio::error_code& ec)
343   {
344     return this->get_service().assign(this->get_implementation(),
345         protocol, native_acceptor, ec);
346   }
347 
348   /// Determine whether the acceptor is open.
is_open() const349   bool is_open() const
350   {
351     return this->get_service().is_open(this->get_implementation());
352   }
353 
354   /// Bind the acceptor to the given local endpoint.
355   /**
356    * This function binds the socket acceptor to the specified endpoint on the
357    * local machine.
358    *
359    * @param endpoint An endpoint on the local machine to which the socket
360    * acceptor will be bound.
361    *
362    * @throws asio::system_error Thrown on failure.
363    *
364    * @par Example
365    * @code
366    * asio::ip::tcp::acceptor acceptor(io_service);
367    * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 12345);
368    * acceptor.open(endpoint.protocol());
369    * acceptor.bind(endpoint);
370    * @endcode
371    */
bind(const endpoint_type & endpoint)372   void bind(const endpoint_type& endpoint)
373   {
374     asio::error_code ec;
375     this->get_service().bind(this->get_implementation(), endpoint, ec);
376     asio::detail::throw_error(ec, "bind");
377   }
378 
379   /// Bind the acceptor to the given local endpoint.
380   /**
381    * This function binds the socket acceptor to the specified endpoint on the
382    * local machine.
383    *
384    * @param endpoint An endpoint on the local machine to which the socket
385    * acceptor will be bound.
386    *
387    * @param ec Set to indicate what error occurred, if any.
388    *
389    * @par Example
390    * @code
391    * asio::ip::tcp::acceptor acceptor(io_service);
392    * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 12345);
393    * acceptor.open(endpoint.protocol());
394    * asio::error_code ec;
395    * acceptor.bind(endpoint, ec);
396    * if (ec)
397    * {
398    *   // An error occurred.
399    * }
400    * @endcode
401    */
bind(const endpoint_type & endpoint,asio::error_code & ec)402   asio::error_code bind(const endpoint_type& endpoint,
403       asio::error_code& ec)
404   {
405     return this->get_service().bind(this->get_implementation(), endpoint, ec);
406   }
407 
408   /// Place the acceptor into the state where it will listen for new
409   /// connections.
410   /**
411    * This function puts the socket acceptor into the state where it may accept
412    * new connections.
413    *
414    * @param backlog The maximum length of the queue of pending connections.
415    *
416    * @throws asio::system_error Thrown on failure.
417    */
listen(int backlog=socket_base::max_connections)418   void listen(int backlog = socket_base::max_connections)
419   {
420     asio::error_code ec;
421     this->get_service().listen(this->get_implementation(), backlog, ec);
422     asio::detail::throw_error(ec, "listen");
423   }
424 
425   /// Place the acceptor into the state where it will listen for new
426   /// connections.
427   /**
428    * This function puts the socket acceptor into the state where it may accept
429    * new connections.
430    *
431    * @param backlog The maximum length of the queue of pending connections.
432    *
433    * @param ec Set to indicate what error occurred, if any.
434    *
435    * @par Example
436    * @code
437    * asio::ip::tcp::acceptor acceptor(io_service);
438    * ...
439    * asio::error_code ec;
440    * acceptor.listen(asio::socket_base::max_connections, ec);
441    * if (ec)
442    * {
443    *   // An error occurred.
444    * }
445    * @endcode
446    */
listen(int backlog,asio::error_code & ec)447   asio::error_code listen(int backlog, asio::error_code& ec)
448   {
449     return this->get_service().listen(this->get_implementation(), backlog, ec);
450   }
451 
452   /// Close the acceptor.
453   /**
454    * This function is used to close the acceptor. Any asynchronous accept
455    * operations will be cancelled immediately.
456    *
457    * A subsequent call to open() is required before the acceptor can again be
458    * used to again perform socket accept operations.
459    *
460    * @throws asio::system_error Thrown on failure.
461    */
close()462   void close()
463   {
464     asio::error_code ec;
465     this->get_service().close(this->get_implementation(), ec);
466     asio::detail::throw_error(ec, "close");
467   }
468 
469   /// Close the acceptor.
470   /**
471    * This function is used to close the acceptor. Any asynchronous accept
472    * operations will be cancelled immediately.
473    *
474    * A subsequent call to open() is required before the acceptor can again be
475    * used to again perform socket accept operations.
476    *
477    * @param ec Set to indicate what error occurred, if any.
478    *
479    * @par Example
480    * @code
481    * asio::ip::tcp::acceptor acceptor(io_service);
482    * ...
483    * asio::error_code ec;
484    * acceptor.close(ec);
485    * if (ec)
486    * {
487    *   // An error occurred.
488    * }
489    * @endcode
490    */
close(asio::error_code & ec)491   asio::error_code close(asio::error_code& ec)
492   {
493     return this->get_service().close(this->get_implementation(), ec);
494   }
495 
496   /// (Deprecated: Use native_handle().) Get the native acceptor representation.
497   /**
498    * This function may be used to obtain the underlying representation of the
499    * acceptor. This is intended to allow access to native acceptor functionality
500    * that is not otherwise provided.
501    */
native()502   native_type native()
503   {
504     return this->get_service().native_handle(this->get_implementation());
505   }
506 
507   /// Get the native acceptor representation.
508   /**
509    * This function may be used to obtain the underlying representation of the
510    * acceptor. This is intended to allow access to native acceptor functionality
511    * that is not otherwise provided.
512    */
native_handle()513   native_handle_type native_handle()
514   {
515     return this->get_service().native_handle(this->get_implementation());
516   }
517 
518   /// Cancel all asynchronous operations associated with the acceptor.
519   /**
520    * This function causes all outstanding asynchronous connect, send and receive
521    * operations to finish immediately, and the handlers for cancelled operations
522    * will be passed the asio::error::operation_aborted error.
523    *
524    * @throws asio::system_error Thrown on failure.
525    */
cancel()526   void cancel()
527   {
528     asio::error_code ec;
529     this->get_service().cancel(this->get_implementation(), ec);
530     asio::detail::throw_error(ec, "cancel");
531   }
532 
533   /// Cancel all asynchronous operations associated with the acceptor.
534   /**
535    * This function causes all outstanding asynchronous connect, send and receive
536    * operations to finish immediately, and the handlers for cancelled operations
537    * will be passed the asio::error::operation_aborted error.
538    *
539    * @param ec Set to indicate what error occurred, if any.
540    */
cancel(asio::error_code & ec)541   asio::error_code cancel(asio::error_code& ec)
542   {
543     return this->get_service().cancel(this->get_implementation(), ec);
544   }
545 
546   /// Set an option on the acceptor.
547   /**
548    * This function is used to set an option on the acceptor.
549    *
550    * @param option The new option value to be set on the acceptor.
551    *
552    * @throws asio::system_error Thrown on failure.
553    *
554    * @sa SettableSocketOption @n
555    * asio::socket_base::reuse_address
556    * asio::socket_base::enable_connection_aborted
557    *
558    * @par Example
559    * Setting the SOL_SOCKET/SO_REUSEADDR option:
560    * @code
561    * asio::ip::tcp::acceptor acceptor(io_service);
562    * ...
563    * asio::ip::tcp::acceptor::reuse_address option(true);
564    * acceptor.set_option(option);
565    * @endcode
566    */
567   template <typename SettableSocketOption>
set_option(const SettableSocketOption & option)568   void set_option(const SettableSocketOption& option)
569   {
570     asio::error_code ec;
571     this->get_service().set_option(this->get_implementation(), option, ec);
572     asio::detail::throw_error(ec, "set_option");
573   }
574 
575   /// Set an option on the acceptor.
576   /**
577    * This function is used to set an option on the acceptor.
578    *
579    * @param option The new option value to be set on the acceptor.
580    *
581    * @param ec Set to indicate what error occurred, if any.
582    *
583    * @sa SettableSocketOption @n
584    * asio::socket_base::reuse_address
585    * asio::socket_base::enable_connection_aborted
586    *
587    * @par Example
588    * Setting the SOL_SOCKET/SO_REUSEADDR option:
589    * @code
590    * asio::ip::tcp::acceptor acceptor(io_service);
591    * ...
592    * asio::ip::tcp::acceptor::reuse_address option(true);
593    * asio::error_code ec;
594    * acceptor.set_option(option, ec);
595    * if (ec)
596    * {
597    *   // An error occurred.
598    * }
599    * @endcode
600    */
601   template <typename SettableSocketOption>
set_option(const SettableSocketOption & option,asio::error_code & ec)602   asio::error_code set_option(const SettableSocketOption& option,
603       asio::error_code& ec)
604   {
605     return this->get_service().set_option(
606         this->get_implementation(), option, ec);
607   }
608 
609   /// Get an option from the acceptor.
610   /**
611    * This function is used to get the current value of an option on the
612    * acceptor.
613    *
614    * @param option The option value to be obtained from the acceptor.
615    *
616    * @throws asio::system_error Thrown on failure.
617    *
618    * @sa GettableSocketOption @n
619    * asio::socket_base::reuse_address
620    *
621    * @par Example
622    * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
623    * @code
624    * asio::ip::tcp::acceptor acceptor(io_service);
625    * ...
626    * asio::ip::tcp::acceptor::reuse_address option;
627    * acceptor.get_option(option);
628    * bool is_set = option.get();
629    * @endcode
630    */
631   template <typename GettableSocketOption>
get_option(GettableSocketOption & option)632   void get_option(GettableSocketOption& option)
633   {
634     asio::error_code ec;
635     this->get_service().get_option(this->get_implementation(), option, ec);
636     asio::detail::throw_error(ec, "get_option");
637   }
638 
639   /// Get an option from the acceptor.
640   /**
641    * This function is used to get the current value of an option on the
642    * acceptor.
643    *
644    * @param option The option value to be obtained from the acceptor.
645    *
646    * @param ec Set to indicate what error occurred, if any.
647    *
648    * @sa GettableSocketOption @n
649    * asio::socket_base::reuse_address
650    *
651    * @par Example
652    * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
653    * @code
654    * asio::ip::tcp::acceptor acceptor(io_service);
655    * ...
656    * asio::ip::tcp::acceptor::reuse_address option;
657    * asio::error_code ec;
658    * acceptor.get_option(option, ec);
659    * if (ec)
660    * {
661    *   // An error occurred.
662    * }
663    * bool is_set = option.get();
664    * @endcode
665    */
666   template <typename GettableSocketOption>
get_option(GettableSocketOption & option,asio::error_code & ec)667   asio::error_code get_option(GettableSocketOption& option,
668       asio::error_code& ec)
669   {
670     return this->get_service().get_option(
671         this->get_implementation(), option, ec);
672   }
673 
674   /// Perform an IO control command on the acceptor.
675   /**
676    * This function is used to execute an IO control command on the acceptor.
677    *
678    * @param command The IO control command to be performed on the acceptor.
679    *
680    * @throws asio::system_error Thrown on failure.
681    *
682    * @sa IoControlCommand @n
683    * asio::socket_base::non_blocking_io
684    *
685    * @par Example
686    * Getting the number of bytes ready to read:
687    * @code
688    * asio::ip::tcp::acceptor acceptor(io_service);
689    * ...
690    * asio::ip::tcp::acceptor::non_blocking_io command(true);
691    * socket.io_control(command);
692    * @endcode
693    */
694   template <typename IoControlCommand>
io_control(IoControlCommand & command)695   void io_control(IoControlCommand& command)
696   {
697     asio::error_code ec;
698     this->get_service().io_control(this->get_implementation(), command, ec);
699     asio::detail::throw_error(ec, "io_control");
700   }
701 
702   /// Perform an IO control command on the acceptor.
703   /**
704    * This function is used to execute an IO control command on the acceptor.
705    *
706    * @param command The IO control command to be performed on the acceptor.
707    *
708    * @param ec Set to indicate what error occurred, if any.
709    *
710    * @sa IoControlCommand @n
711    * asio::socket_base::non_blocking_io
712    *
713    * @par Example
714    * Getting the number of bytes ready to read:
715    * @code
716    * asio::ip::tcp::acceptor acceptor(io_service);
717    * ...
718    * asio::ip::tcp::acceptor::non_blocking_io command(true);
719    * asio::error_code ec;
720    * socket.io_control(command, ec);
721    * if (ec)
722    * {
723    *   // An error occurred.
724    * }
725    * @endcode
726    */
727   template <typename IoControlCommand>
io_control(IoControlCommand & command,asio::error_code & ec)728   asio::error_code io_control(IoControlCommand& command,
729       asio::error_code& ec)
730   {
731     return this->get_service().io_control(
732         this->get_implementation(), command, ec);
733   }
734 
735   /// Gets the non-blocking mode of the acceptor.
736   /**
737    * @returns @c true if the acceptor's synchronous operations will fail with
738    * asio::error::would_block if they are unable to perform the requested
739    * operation immediately. If @c false, synchronous operations will block
740    * until complete.
741    *
742    * @note The non-blocking mode has no effect on the behaviour of asynchronous
743    * operations. Asynchronous operations will never fail with the error
744    * asio::error::would_block.
745    */
non_blocking() const746   bool non_blocking() const
747   {
748     return this->get_service().non_blocking(this->get_implementation());
749   }
750 
751   /// Sets the non-blocking mode of the acceptor.
752   /**
753    * @param mode If @c true, the acceptor's synchronous operations will fail
754    * with asio::error::would_block if they are unable to perform the
755    * requested operation immediately. If @c false, synchronous operations will
756    * block until complete.
757    *
758    * @throws asio::system_error Thrown on failure.
759    *
760    * @note The non-blocking mode has no effect on the behaviour of asynchronous
761    * operations. Asynchronous operations will never fail with the error
762    * asio::error::would_block.
763    */
non_blocking(bool mode)764   void non_blocking(bool mode)
765   {
766     asio::error_code ec;
767     this->get_service().non_blocking(this->get_implementation(), mode, ec);
768     asio::detail::throw_error(ec, "non_blocking");
769   }
770 
771   /// Sets the non-blocking mode of the acceptor.
772   /**
773    * @param mode If @c true, the acceptor's synchronous operations will fail
774    * with asio::error::would_block if they are unable to perform the
775    * requested operation immediately. If @c false, synchronous operations will
776    * block until complete.
777    *
778    * @param ec Set to indicate what error occurred, if any.
779    *
780    * @note The non-blocking mode has no effect on the behaviour of asynchronous
781    * operations. Asynchronous operations will never fail with the error
782    * asio::error::would_block.
783    */
non_blocking(bool mode,asio::error_code & ec)784   asio::error_code non_blocking(
785       bool mode, asio::error_code& ec)
786   {
787     return this->get_service().non_blocking(
788         this->get_implementation(), mode, ec);
789   }
790 
791   /// Gets the non-blocking mode of the native acceptor implementation.
792   /**
793    * This function is used to retrieve the non-blocking mode of the underlying
794    * native acceptor. This mode has no effect on the behaviour of the acceptor
795    * object's synchronous operations.
796    *
797    * @returns @c true if the underlying acceptor is in non-blocking mode and
798    * direct system calls may fail with asio::error::would_block (or the
799    * equivalent system error).
800    *
801    * @note The current non-blocking mode is cached by the acceptor object.
802    * Consequently, the return value may be incorrect if the non-blocking mode
803    * was set directly on the native acceptor.
804    */
native_non_blocking() const805   bool native_non_blocking() const
806   {
807     return this->get_service().native_non_blocking(this->get_implementation());
808   }
809 
810   /// Sets the non-blocking mode of the native acceptor implementation.
811   /**
812    * This function is used to modify the non-blocking mode of the underlying
813    * native acceptor. It has no effect on the behaviour of the acceptor object's
814    * synchronous operations.
815    *
816    * @param mode If @c true, the underlying acceptor is put into non-blocking
817    * mode and direct system calls may fail with asio::error::would_block
818    * (or the equivalent system error).
819    *
820    * @throws asio::system_error Thrown on failure. If the @c mode is
821    * @c false, but the current value of @c non_blocking() is @c true, this
822    * function fails with asio::error::invalid_argument, as the
823    * combination does not make sense.
824    */
native_non_blocking(bool mode)825   void native_non_blocking(bool mode)
826   {
827     asio::error_code ec;
828     this->get_service().native_non_blocking(
829         this->get_implementation(), mode, ec);
830     asio::detail::throw_error(ec, "native_non_blocking");
831   }
832 
833   /// Sets the non-blocking mode of the native acceptor implementation.
834   /**
835    * This function is used to modify the non-blocking mode of the underlying
836    * native acceptor. It has no effect on the behaviour of the acceptor object's
837    * synchronous operations.
838    *
839    * @param mode If @c true, the underlying acceptor is put into non-blocking
840    * mode and direct system calls may fail with asio::error::would_block
841    * (or the equivalent system error).
842    *
843    * @param ec Set to indicate what error occurred, if any. If the @c mode is
844    * @c false, but the current value of @c non_blocking() is @c true, this
845    * function fails with asio::error::invalid_argument, as the
846    * combination does not make sense.
847    */
native_non_blocking(bool mode,asio::error_code & ec)848   asio::error_code native_non_blocking(
849       bool mode, asio::error_code& ec)
850   {
851     return this->get_service().native_non_blocking(
852         this->get_implementation(), mode, ec);
853   }
854 
855   /// Get the local endpoint of the acceptor.
856   /**
857    * This function is used to obtain the locally bound endpoint of the acceptor.
858    *
859    * @returns An object that represents the local endpoint of the acceptor.
860    *
861    * @throws asio::system_error Thrown on failure.
862    *
863    * @par Example
864    * @code
865    * asio::ip::tcp::acceptor acceptor(io_service);
866    * ...
867    * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
868    * @endcode
869    */
local_endpoint() const870   endpoint_type local_endpoint() const
871   {
872     asio::error_code ec;
873     endpoint_type ep = this->get_service().local_endpoint(
874         this->get_implementation(), ec);
875     asio::detail::throw_error(ec, "local_endpoint");
876     return ep;
877   }
878 
879   /// Get the local endpoint of the acceptor.
880   /**
881    * This function is used to obtain the locally bound endpoint of the acceptor.
882    *
883    * @param ec Set to indicate what error occurred, if any.
884    *
885    * @returns An object that represents the local endpoint of the acceptor.
886    * Returns a default-constructed endpoint object if an error occurred and the
887    * error handler did not throw an exception.
888    *
889    * @par Example
890    * @code
891    * asio::ip::tcp::acceptor acceptor(io_service);
892    * ...
893    * asio::error_code ec;
894    * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);
895    * if (ec)
896    * {
897    *   // An error occurred.
898    * }
899    * @endcode
900    */
local_endpoint(asio::error_code & ec) const901   endpoint_type local_endpoint(asio::error_code& ec) const
902   {
903     return this->get_service().local_endpoint(this->get_implementation(), ec);
904   }
905 
906   /// Accept a new connection.
907   /**
908    * This function is used to accept a new connection from a peer into the
909    * given socket. The function call will block until a new connection has been
910    * accepted successfully or an error occurs.
911    *
912    * @param peer The socket into which the new connection will be accepted.
913    *
914    * @throws asio::system_error Thrown on failure.
915    *
916    * @par Example
917    * @code
918    * asio::ip::tcp::acceptor acceptor(io_service);
919    * ...
920    * asio::ip::tcp::socket socket(io_service);
921    * acceptor.accept(socket);
922    * @endcode
923    */
924   template <typename Protocol1, typename SocketService>
accept(basic_socket<Protocol1,SocketService> & peer,typename enable_if<is_convertible<Protocol,Protocol1>::value>::type * =0)925   void accept(basic_socket<Protocol1, SocketService>& peer,
926       typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
927   {
928     asio::error_code ec;
929     this->get_service().accept(this->get_implementation(),
930         peer, static_cast<endpoint_type*>(0), ec);
931     asio::detail::throw_error(ec, "accept");
932   }
933 
934   /// Accept a new connection.
935   /**
936    * This function is used to accept a new connection from a peer into the
937    * given socket. The function call will block until a new connection has been
938    * accepted successfully or an error occurs.
939    *
940    * @param peer The socket into which the new connection will be accepted.
941    *
942    * @param ec Set to indicate what error occurred, if any.
943    *
944    * @par Example
945    * @code
946    * asio::ip::tcp::acceptor acceptor(io_service);
947    * ...
948    * asio::ip::tcp::soocket socket(io_service);
949    * asio::error_code ec;
950    * acceptor.accept(socket, ec);
951    * if (ec)
952    * {
953    *   // An error occurred.
954    * }
955    * @endcode
956    */
957   template <typename Protocol1, typename SocketService>
accept(basic_socket<Protocol1,SocketService> & peer,asio::error_code & ec,typename enable_if<is_convertible<Protocol,Protocol1>::value>::type * =0)958   asio::error_code accept(
959       basic_socket<Protocol1, SocketService>& peer,
960       asio::error_code& ec,
961       typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
962   {
963     return this->get_service().accept(this->get_implementation(),
964         peer, static_cast<endpoint_type*>(0), ec);
965   }
966 
967   /// Start an asynchronous accept.
968   /**
969    * This function is used to asynchronously accept a new connection into a
970    * socket. The function call always returns immediately.
971    *
972    * @param peer The socket into which the new connection will be accepted.
973    * Ownership of the peer object is retained by the caller, which must
974    * guarantee that it is valid until the handler is called.
975    *
976    * @param handler The handler to be called when the accept operation
977    * completes. Copies will be made of the handler as required. The function
978    * signature of the handler must be:
979    * @code void handler(
980    *   const asio::error_code& error // Result of operation.
981    * ); @endcode
982    * Regardless of whether the asynchronous operation completes immediately or
983    * not, the handler will not be invoked from within this function. Invocation
984    * of the handler will be performed in a manner equivalent to using
985    * asio::io_service::post().
986    *
987    * @par Example
988    * @code
989    * void accept_handler(const asio::error_code& error)
990    * {
991    *   if (!error)
992    *   {
993    *     // Accept succeeded.
994    *   }
995    * }
996    *
997    * ...
998    *
999    * asio::ip::tcp::acceptor acceptor(io_service);
1000    * ...
1001    * asio::ip::tcp::socket socket(io_service);
1002    * acceptor.async_accept(socket, accept_handler);
1003    * @endcode
1004    */
1005   template <typename Protocol1, typename SocketService, typename AcceptHandler>
ASIO_INITFN_RESULT_TYPE(AcceptHandler,void (asio::error_code))1006   ASIO_INITFN_RESULT_TYPE(AcceptHandler,
1007       void (asio::error_code))
1008   async_accept(basic_socket<Protocol1, SocketService>& peer,
1009       ASIO_MOVE_ARG(AcceptHandler) handler,
1010       typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
1011   {
1012     // If you get an error on the following line it means that your handler does
1013     // not meet the documented type requirements for a AcceptHandler.
1014     ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
1015 
1016     return this->get_service().async_accept(this->get_implementation(),
1017         peer, static_cast<endpoint_type*>(0),
1018         ASIO_MOVE_CAST(AcceptHandler)(handler));
1019   }
1020 
1021   /// Accept a new connection and obtain the endpoint of the peer
1022   /**
1023    * This function is used to accept a new connection from a peer into the
1024    * given socket, and additionally provide the endpoint of the remote peer.
1025    * The function call will block until a new connection has been accepted
1026    * successfully or an error occurs.
1027    *
1028    * @param peer The socket into which the new connection will be accepted.
1029    *
1030    * @param peer_endpoint An endpoint object which will receive the endpoint of
1031    * the remote peer.
1032    *
1033    * @throws asio::system_error Thrown on failure.
1034    *
1035    * @par Example
1036    * @code
1037    * asio::ip::tcp::acceptor acceptor(io_service);
1038    * ...
1039    * asio::ip::tcp::socket socket(io_service);
1040    * asio::ip::tcp::endpoint endpoint;
1041    * acceptor.accept(socket, endpoint);
1042    * @endcode
1043    */
1044   template <typename SocketService>
accept(basic_socket<protocol_type,SocketService> & peer,endpoint_type & peer_endpoint)1045   void accept(basic_socket<protocol_type, SocketService>& peer,
1046       endpoint_type& peer_endpoint)
1047   {
1048     asio::error_code ec;
1049     this->get_service().accept(this->get_implementation(),
1050         peer, &peer_endpoint, ec);
1051     asio::detail::throw_error(ec, "accept");
1052   }
1053 
1054   /// Accept a new connection and obtain the endpoint of the peer
1055   /**
1056    * This function is used to accept a new connection from a peer into the
1057    * given socket, and additionally provide the endpoint of the remote peer.
1058    * The function call will block until a new connection has been accepted
1059    * successfully or an error occurs.
1060    *
1061    * @param peer The socket into which the new connection will be accepted.
1062    *
1063    * @param peer_endpoint An endpoint object which will receive the endpoint of
1064    * the remote peer.
1065    *
1066    * @param ec Set to indicate what error occurred, if any.
1067    *
1068    * @par Example
1069    * @code
1070    * asio::ip::tcp::acceptor acceptor(io_service);
1071    * ...
1072    * asio::ip::tcp::socket socket(io_service);
1073    * asio::ip::tcp::endpoint endpoint;
1074    * asio::error_code ec;
1075    * acceptor.accept(socket, endpoint, ec);
1076    * if (ec)
1077    * {
1078    *   // An error occurred.
1079    * }
1080    * @endcode
1081    */
1082   template <typename SocketService>
accept(basic_socket<protocol_type,SocketService> & peer,endpoint_type & peer_endpoint,asio::error_code & ec)1083   asio::error_code accept(
1084       basic_socket<protocol_type, SocketService>& peer,
1085       endpoint_type& peer_endpoint, asio::error_code& ec)
1086   {
1087     return this->get_service().accept(
1088         this->get_implementation(), peer, &peer_endpoint, ec);
1089   }
1090 
1091   /// Start an asynchronous accept.
1092   /**
1093    * This function is used to asynchronously accept a new connection into a
1094    * socket, and additionally obtain the endpoint of the remote peer. The
1095    * function call always returns immediately.
1096    *
1097    * @param peer The socket into which the new connection will be accepted.
1098    * Ownership of the peer object is retained by the caller, which must
1099    * guarantee that it is valid until the handler is called.
1100    *
1101    * @param peer_endpoint An endpoint object into which the endpoint of the
1102    * remote peer will be written. Ownership of the peer_endpoint object is
1103    * retained by the caller, which must guarantee that it is valid until the
1104    * handler is called.
1105    *
1106    * @param handler The handler to be called when the accept operation
1107    * completes. Copies will be made of the handler as required. The function
1108    * signature of the handler must be:
1109    * @code void handler(
1110    *   const asio::error_code& error // Result of operation.
1111    * ); @endcode
1112    * Regardless of whether the asynchronous operation completes immediately or
1113    * not, the handler will not be invoked from within this function. Invocation
1114    * of the handler will be performed in a manner equivalent to using
1115    * asio::io_service::post().
1116    */
1117   template <typename SocketService, typename AcceptHandler>
ASIO_INITFN_RESULT_TYPE(AcceptHandler,void (asio::error_code))1118   ASIO_INITFN_RESULT_TYPE(AcceptHandler,
1119       void (asio::error_code))
1120   async_accept(basic_socket<protocol_type, SocketService>& peer,
1121       endpoint_type& peer_endpoint, ASIO_MOVE_ARG(AcceptHandler) handler)
1122   {
1123     // If you get an error on the following line it means that your handler does
1124     // not meet the documented type requirements for a AcceptHandler.
1125     ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
1126 
1127     return this->get_service().async_accept(this->get_implementation(), peer,
1128         &peer_endpoint, ASIO_MOVE_CAST(AcceptHandler)(handler));
1129   }
1130 };
1131 
1132 } // namespace asio
1133 
1134 #include "asio/detail/pop_options.hpp"
1135 
1136 #endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP
1137