19 #ifndef IRCCD_ACCEPTOR_HPP
20 #define IRCCD_ACCEPTOR_HPP
27 #include <irccd/sysconfig.hpp>
32 #include <system_error>
34 #include <boost/asio.hpp>
35 #include <boost/filesystem/path.hpp>
37 #if defined(IRCCD_HAVE_SSL)
38 # include <boost/asio/ssl.hpp>
57 using handler = std::function<void (std::error_code, std::shared_ptr<stream>)>;
89 template <
typename Acceptor>
99 bool is_accepting_{
false};
135 auto get_service() const noexcept -> const boost::asio::io_context&;
166 template <typename Socket, typename Handler>
170 template <typename Acceptor>
177 template <
typename Acceptor>
184 template <
typename Acceptor>
190 template <
typename Acceptor>
196 template <
typename Acceptor>
202 template <
typename Acceptor>
208 template <
typename Acceptor>
209 template <
typename Socket,
typename Handler>
213 assert(!is_accepting_);
215 is_accepting_ =
true;
222 is_accepting_ =
false;
239 void open(
bool ipv6);
240 void set(
bool ipv4,
bool ipv6);
241 void bind(
const std::string& address, std::uint16_t port,
bool ipv6);
281 inline void ip_acceptor::open(
bool ipv6)
283 using boost::asio::ip::tcp;
291 inline void ip_acceptor::set(
bool ipv4,
bool ipv6)
293 using boost::asio::socket_base;
294 using boost::asio::ip::v6_only;
299 acceptor_.set_option(socket_base::reuse_address(
true));
302 inline void ip_acceptor::bind(
const std::string& address, std::uint16_t port,
bool ipv6)
304 using boost::asio::ip::make_address_v4;
305 using boost::asio::ip::make_address_v6;
306 using boost::asio::ip::tcp;
311 ep = tcp::endpoint(ipv6 ? tcp::v6() : tcp::v4(), port);
313 ep = tcp::endpoint(make_address_v6(address), port);
315 ep = tcp::endpoint(make_address_v4(address), port);
328 assert(ipv4 || ipv6);
332 bind(address, port, ipv6);
341 handler(std::move(code), nullptr);
343 handler(std::move(code), std::move(stream));
351 #if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
367 const boost::filesystem::path& path);
386 const boost::filesystem::path& path)
389 using boost::asio::socket_base;
391 std::remove(path.string().c_str());
394 acceptor_.set_option(socket_base::reuse_address(
true));
405 handler(std::move(code), nullptr);
407 handler(std::move(code), std::move(stream));
417 #if defined(IRCCD_HAVE_SSL)
444 template <
typename SocketAcceptor>
447 using socket_type =
typename SocketAcceptor::socket_type;
449 std::shared_ptr<boost::asio::ssl::context> context_;
450 SocketAcceptor acceptor_;
459 template <
typename... Args>
460 tls_acceptor(boost::asio::ssl::context context, Args&&... args);
468 template <
typename SocketAcceptor>
469 template <
typename... Args>
471 : context_(
std::make_shared<boost::asio::ssl::context>(
std::move(context)))
472 , acceptor_(
std::forward<Args>(args)...)
476 template <
typename SocketAcceptor>
479 auto client = std::make_shared<tls_stream<socket_type>>(acceptor_.get_service(), context_);
481 acceptor_.accept(client->get_socket().lowest_layer(), [
handler, client] (
auto code) {
482 using boost::asio::ssl::stream_base;
485 handler(std::move(code),
nullptr);
489 client->get_socket().async_handshake(stream_base::server, [
handler, client] (
auto code) {
491 handler(std::move(code),
nullptr);
493 handler(std::move(code), std::move(client));
503 #if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
510 #endif // !BOOST_ASIO_HAS_LOCAL_SOCKETS
512 #endif // !IRCCD_HAVE_SSL
518 #endif // !IRCCD_ACCEPTOR_HPP