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 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 clmdep_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 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 45 * clmdep_asio::ip::tcp::endpoint endpoint(clmdep_asio::ip::tcp::v4(), port); 46 * acceptor.open(endpoint.protocol()); 47 * acceptor.set_option(clmdep_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(clmdep_asio::io_service & io_service)82 explicit basic_socket_acceptor(clmdep_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 clmdep_asio::system_error Thrown on failure. 98 */ basic_socket_acceptor(clmdep_asio::io_service & io_service,const protocol_type & protocol)99 basic_socket_acceptor(clmdep_asio::io_service& io_service, 100 const protocol_type& protocol) 101 : basic_io_object<SocketAcceptorService>(io_service) 102 { 103 clmdep_asio::error_code ec; 104 this->get_service().open(this->get_implementation(), protocol, ec); 105 clmdep_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 clmdep_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(clmdep_asio::io_service & io_service,const endpoint_type & endpoint,bool reuse_addr=true)135 basic_socket_acceptor(clmdep_asio::io_service& io_service, 136 const endpoint_type& endpoint, bool reuse_addr = true) 137 : basic_io_object<SocketAcceptorService>(io_service) 138 { 139 clmdep_asio::error_code ec; 140 const protocol_type protocol = endpoint.protocol(); 141 this->get_service().open(this->get_implementation(), protocol, ec); 142 clmdep_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 clmdep_asio::detail::throw_error(ec, "set_option"); 148 } 149 this->get_service().bind(this->get_implementation(), endpoint, ec); 150 clmdep_asio::detail::throw_error(ec, "bind"); 151 this->get_service().listen(this->get_implementation(), 152 socket_base::max_connections, ec); 153 clmdep_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 clmdep_asio::system_error Thrown on failure. 170 */ basic_socket_acceptor(clmdep_asio::io_service & io_service,const protocol_type & protocol,const native_handle_type & native_acceptor)171 basic_socket_acceptor(clmdep_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 clmdep_asio::error_code ec; 176 this->get_service().assign(this->get_implementation(), 177 protocol, native_acceptor, ec); 178 clmdep_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 clmdep_asio::system_error Thrown on failure. 272 * 273 * @par Example 274 * @code 275 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 276 * acceptor.open(clmdep_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 clmdep_asio::error_code ec; 282 this->get_service().open(this->get_implementation(), protocol, ec); 283 clmdep_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 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 298 * clmdep_asio::error_code ec; 299 * acceptor.open(clmdep_asio::ip::tcp::v4(), ec); 300 * if (ec) 301 * { 302 * // An error occurred. 303 * } 304 * @endcode 305 */ open(const protocol_type & protocol,clmdep_asio::error_code & ec)306 clmdep_asio::error_code open(const protocol_type& protocol, 307 clmdep_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 clmdep_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 clmdep_asio::error_code ec; 326 this->get_service().assign(this->get_implementation(), 327 protocol, native_acceptor, ec); 328 clmdep_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,clmdep_asio::error_code & ec)341 clmdep_asio::error_code assign(const protocol_type& protocol, 342 const native_handle_type& native_acceptor, clmdep_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 clmdep_asio::system_error Thrown on failure. 363 * 364 * @par Example 365 * @code 366 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 367 * clmdep_asio::ip::tcp::endpoint endpoint(clmdep_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 clmdep_asio::error_code ec; 375 this->get_service().bind(this->get_implementation(), endpoint, ec); 376 clmdep_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 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 392 * clmdep_asio::ip::tcp::endpoint endpoint(clmdep_asio::ip::tcp::v4(), 12345); 393 * acceptor.open(endpoint.protocol()); 394 * clmdep_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,clmdep_asio::error_code & ec)402 clmdep_asio::error_code bind(const endpoint_type& endpoint, 403 clmdep_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 clmdep_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 clmdep_asio::error_code ec; 421 this->get_service().listen(this->get_implementation(), backlog, ec); 422 clmdep_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 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 438 * ... 439 * clmdep_asio::error_code ec; 440 * acceptor.listen(clmdep_asio::socket_base::max_connections, ec); 441 * if (ec) 442 * { 443 * // An error occurred. 444 * } 445 * @endcode 446 */ listen(int backlog,clmdep_asio::error_code & ec)447 clmdep_asio::error_code listen(int backlog, clmdep_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 clmdep_asio::system_error Thrown on failure. 461 */ close()462 void close() 463 { 464 clmdep_asio::error_code ec; 465 this->get_service().close(this->get_implementation(), ec); 466 clmdep_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 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 482 * ... 483 * clmdep_asio::error_code ec; 484 * acceptor.close(ec); 485 * if (ec) 486 * { 487 * // An error occurred. 488 * } 489 * @endcode 490 */ close(clmdep_asio::error_code & ec)491 clmdep_asio::error_code close(clmdep_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 clmdep_asio::error::operation_aborted error. 523 * 524 * @throws clmdep_asio::system_error Thrown on failure. 525 */ cancel()526 void cancel() 527 { 528 clmdep_asio::error_code ec; 529 this->get_service().cancel(this->get_implementation(), ec); 530 clmdep_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 clmdep_asio::error::operation_aborted error. 538 * 539 * @param ec Set to indicate what error occurred, if any. 540 */ cancel(clmdep_asio::error_code & ec)541 clmdep_asio::error_code cancel(clmdep_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 clmdep_asio::system_error Thrown on failure. 553 * 554 * @sa SettableSocketOption @n 555 * clmdep_asio::socket_base::reuse_address 556 * clmdep_asio::socket_base::enable_connection_aborted 557 * 558 * @par Example 559 * Setting the SOL_SOCKET/SO_REUSEADDR option: 560 * @code 561 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 562 * ... 563 * clmdep_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 clmdep_asio::error_code ec; 571 this->get_service().set_option(this->get_implementation(), option, ec); 572 clmdep_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 * clmdep_asio::socket_base::reuse_address 585 * clmdep_asio::socket_base::enable_connection_aborted 586 * 587 * @par Example 588 * Setting the SOL_SOCKET/SO_REUSEADDR option: 589 * @code 590 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 591 * ... 592 * clmdep_asio::ip::tcp::acceptor::reuse_address option(true); 593 * clmdep_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,clmdep_asio::error_code & ec)602 clmdep_asio::error_code set_option(const SettableSocketOption& option, 603 clmdep_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 clmdep_asio::system_error Thrown on failure. 617 * 618 * @sa GettableSocketOption @n 619 * clmdep_asio::socket_base::reuse_address 620 * 621 * @par Example 622 * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: 623 * @code 624 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 625 * ... 626 * clmdep_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 clmdep_asio::error_code ec; 635 this->get_service().get_option(this->get_implementation(), option, ec); 636 clmdep_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 * clmdep_asio::socket_base::reuse_address 650 * 651 * @par Example 652 * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: 653 * @code 654 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 655 * ... 656 * clmdep_asio::ip::tcp::acceptor::reuse_address option; 657 * clmdep_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,clmdep_asio::error_code & ec)667 clmdep_asio::error_code get_option(GettableSocketOption& option, 668 clmdep_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 clmdep_asio::system_error Thrown on failure. 681 * 682 * @sa IoControlCommand @n 683 * clmdep_asio::socket_base::non_blocking_io 684 * 685 * @par Example 686 * Getting the number of bytes ready to read: 687 * @code 688 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 689 * ... 690 * clmdep_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 clmdep_asio::error_code ec; 698 this->get_service().io_control(this->get_implementation(), command, ec); 699 clmdep_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 * clmdep_asio::socket_base::non_blocking_io 712 * 713 * @par Example 714 * Getting the number of bytes ready to read: 715 * @code 716 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 717 * ... 718 * clmdep_asio::ip::tcp::acceptor::non_blocking_io command(true); 719 * clmdep_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,clmdep_asio::error_code & ec)728 clmdep_asio::error_code io_control(IoControlCommand& command, 729 clmdep_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 * clmdep_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 * clmdep_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 clmdep_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 clmdep_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 * clmdep_asio::error::would_block. 763 */ non_blocking(bool mode)764 void non_blocking(bool mode) 765 { 766 clmdep_asio::error_code ec; 767 this->get_service().non_blocking(this->get_implementation(), mode, ec); 768 clmdep_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 clmdep_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 * clmdep_asio::error::would_block. 783 */ non_blocking(bool mode,clmdep_asio::error_code & ec)784 clmdep_asio::error_code non_blocking( 785 bool mode, clmdep_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 clmdep_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 clmdep_asio::error::would_block 818 * (or the equivalent system error). 819 * 820 * @throws clmdep_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 clmdep_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 clmdep_asio::error_code ec; 828 this->get_service().native_non_blocking( 829 this->get_implementation(), mode, ec); 830 clmdep_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 clmdep_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 clmdep_asio::error::invalid_argument, as the 846 * combination does not make sense. 847 */ native_non_blocking(bool mode,clmdep_asio::error_code & ec)848 clmdep_asio::error_code native_non_blocking( 849 bool mode, clmdep_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 clmdep_asio::system_error Thrown on failure. 862 * 863 * @par Example 864 * @code 865 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 866 * ... 867 * clmdep_asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); 868 * @endcode 869 */ local_endpoint() const870 endpoint_type local_endpoint() const 871 { 872 clmdep_asio::error_code ec; 873 endpoint_type ep = this->get_service().local_endpoint( 874 this->get_implementation(), ec); 875 clmdep_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 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 892 * ... 893 * clmdep_asio::error_code ec; 894 * clmdep_asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); 895 * if (ec) 896 * { 897 * // An error occurred. 898 * } 899 * @endcode 900 */ local_endpoint(clmdep_asio::error_code & ec) const901 endpoint_type local_endpoint(clmdep_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 clmdep_asio::system_error Thrown on failure. 915 * 916 * @par Example 917 * @code 918 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 919 * ... 920 * clmdep_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 clmdep_asio::error_code ec; 929 this->get_service().accept(this->get_implementation(), 930 peer, static_cast<endpoint_type*>(0), ec); 931 clmdep_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 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 947 * ... 948 * clmdep_asio::ip::tcp::soocket socket(io_service); 949 * clmdep_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,clmdep_asio::error_code & ec,typename enable_if<is_convertible<Protocol,Protocol1>::value>::type * =0)958 clmdep_asio::error_code accept( 959 basic_socket<Protocol1, SocketService>& peer, 960 clmdep_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 clmdep_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 * clmdep_asio::io_service::post(). 986 * 987 * @par Example 988 * @code 989 * void accept_handler(const clmdep_asio::error_code& error) 990 * { 991 * if (!error) 992 * { 993 * // Accept succeeded. 994 * } 995 * } 996 * 997 * ... 998 * 999 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 1000 * ... 1001 * clmdep_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 (clmdep_asio::error_code))1006 ASIO_INITFN_RESULT_TYPE(AcceptHandler, 1007 void (clmdep_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 clmdep_asio::system_error Thrown on failure. 1034 * 1035 * @par Example 1036 * @code 1037 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 1038 * ... 1039 * clmdep_asio::ip::tcp::socket socket(io_service); 1040 * clmdep_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 clmdep_asio::error_code ec; 1049 this->get_service().accept(this->get_implementation(), 1050 peer, &peer_endpoint, ec); 1051 clmdep_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 * clmdep_asio::ip::tcp::acceptor acceptor(io_service); 1071 * ... 1072 * clmdep_asio::ip::tcp::socket socket(io_service); 1073 * clmdep_asio::ip::tcp::endpoint endpoint; 1074 * clmdep_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,clmdep_asio::error_code & ec)1083 clmdep_asio::error_code accept( 1084 basic_socket<protocol_type, SocketService>& peer, 1085 endpoint_type& peer_endpoint, clmdep_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 clmdep_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 * clmdep_asio::io_service::post(). 1116 */ 1117 template <typename SocketService, typename AcceptHandler> ASIO_INITFN_RESULT_TYPE(AcceptHandler,void (clmdep_asio::error_code))1118 ASIO_INITFN_RESULT_TYPE(AcceptHandler, 1119 void (clmdep_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 clmdep_asio 1133 1134 #include "asio/detail/pop_options.hpp" 1135 1136 #endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP 1137