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