1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (C) 2017-2024 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef IO_ACCEPTOR_H
#define IO_ACCEPTOR_H

#ifndef BOOST_ASIO_HPP
#error "asio.hpp must be included before including this, see asiolink.h as to why"
#endif

#include <asiolink/io_service.h>
#include <asiolink/io_socket.h>

namespace isc {
namespace asiolink {

/// @brief Base class for acceptor services in Kea.
///
/// This is a wrapper class for ASIO acceptor service. Classes implementing
/// services for specific protocol types should derive from this class.
///
/// Acceptor is an IO object which accepts incoming connections into a socket
/// object. This socket is then used for data transmission from the client
/// to server and back. The acceptor is continued to be used to accept new
/// connections while the accepted connection is active.
///
/// @tparam ProtocolType ASIO protocol type, e.g. stream_protocol
/// @tparam CallbackType Callback function type which should have the following
/// signature: @c void(const boost::system::error_code&).
template<typename ProtocolType, typename CallbackType>
class IOAcceptor : public IOSocket {
public:

    /// @brief Constructor.
    ///
    /// @param io_service Reference to the IO service.
    explicit IOAcceptor(const IOServicePtr& io_service)
        : IOSocket(), io_service_(io_service),
          acceptor_(new typename ProtocolType::acceptor(io_service_->getInternalIOService())) {
    }

    /// @brief Destructor.
    virtual ~IOAcceptor() { }

    /// @brief Returns file descriptor of the underlying socket.
    virtual int getNative() const {<--- Function in derived class
#if BOOST_VERSION < 106600
        return (acceptor_->native());
#else
        return (acceptor_->native_handle());
#endif
    }

    /// @brief Opens acceptor socket given the endpoint.
    ///
    /// @param endpoint Reference to the endpoint object defining local
    /// acceptor endpoint.
    ///
    /// @tparam EndpointType Endpoint type.
    template<typename EndpointType>
    void open(const EndpointType& endpoint) {
        acceptor_->open(endpoint.getASIOEndpoint().protocol());
    }

    /// @brief Binds socket to an endpoint.
    ///
    /// @param endpoint Reference to the endpoint object defining local
    /// acceptor endpoint.
    ///
    /// @tparam EndpointType Endpoint type.
    template<typename EndpointType>
    void bind(const EndpointType& endpoint) {
        acceptor_->bind(endpoint.getASIOEndpoint());
    }

    /// @brief Sets socket option.
    ///
    /// @param socket_option Reference to the object encapsulating an option to
    /// be set for the socket.
    /// @tparam SettableSocketOption Type of the object encapsulating socket option
    /// being set.
    template<typename SettableSocketOption>
    void setOption(const SettableSocketOption& socket_option) {
        acceptor_->set_option(socket_option);
    }

    /// @brief Starts listening new connections.
    void listen() {
        acceptor_->listen();
    }

    /// @brief Checks if the acceptor is open.
    ///
    /// @return true if acceptor is open.
    bool isOpen() const {
        return (acceptor_->is_open());
    }

    /// @brief Closes the acceptor.
    void close() const {
        acceptor_->close();
    }

protected:

    /// @brief Asynchronously accept new connection.
    ///
    /// This method accepts new connection into the specified socket. When the
    /// new connection arrives or an error occurs the specified callback
    /// function is invoked.
    ///
    /// @param socket Socket into which connection should be accepted.
    /// @param callback Callback function to be invoked when the new connection
    /// arrives.
    /// @tparam SocketType Socket type, e.g. @ref UnixDomainSocket. It must
    /// implement @c getASIOSocket method.
    template<typename SocketType>
    void asyncAcceptInternal(const SocketType& socket,
                             const CallbackType& callback) {
        acceptor_->async_accept(socket.getASIOSocket(), callback);
    }

    /// @brief The IO service used to handle events.
    IOServicePtr io_service_;

    /// @brief Underlying ASIO acceptor implementation.
    boost::shared_ptr<typename ProtocolType::acceptor> acceptor_;

};

} // end of namespace asiolink
} // end of isc

#endif // IO_ACCEPTOR_H