src/corosio/src/tcp_acceptor.cpp

96.8% Lines (61/0/63) 100.0% List of functions (12/0/12)
tcp_acceptor.cpp
f(x) Functions (12)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2026 Steve Gerbino
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #include <boost/corosio/tcp_acceptor.hpp>
12 #include <boost/corosio/socket_option.hpp>
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_HAS_IOCP
16 #include <boost/corosio/native/detail/iocp/win_tcp_acceptor_service.hpp>
17 #else
18 #include <boost/corosio/detail/tcp_acceptor_service.hpp>
19 #endif
20
21 #include <boost/corosio/detail/except.hpp>
22
23 namespace boost::corosio {
24
25 435x tcp_acceptor::~tcp_acceptor()
26 {
27 435x close();
28 435x }
29
30 409x tcp_acceptor::tcp_acceptor(capy::execution_context& ctx)
31 #if BOOST_COROSIO_HAS_IOCP
32 : io_object(create_handle<detail::win_tcp_acceptor_service>(ctx))
33 #else
34 409x : io_object(create_handle<detail::tcp_acceptor_service>(ctx))
35 #endif
36 {
37 409x }
38
39 38x tcp_acceptor::tcp_acceptor(
40 38x capy::execution_context& ctx, endpoint ep, int backlog)
41 38x : tcp_acceptor(ctx)
42 {
43 38x open(ep.is_v6() ? tcp::v6() : tcp::v4());
44 38x set_option(socket_option::reuse_address(true));
45 38x if (auto ec = bind(ep))
46 2x detail::throw_system_error(ec, "tcp_acceptor");
47 36x if (auto ec = listen(backlog))
48 detail::throw_system_error(ec, "tcp_acceptor");
49 38x }
50
51 void
52 411x tcp_acceptor::open(tcp proto)
53 {
54 411x if (is_open())
55 2x return;
56
57 #if BOOST_COROSIO_HAS_IOCP
58 auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
59 #else
60 409x auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
61 #endif
62 818x std::error_code ec = svc.open_acceptor_socket(
63 409x *static_cast<tcp_acceptor::implementation*>(h_.get()), proto.family(),
64 proto.type(), proto.protocol());
65 409x if (ec)
66 detail::throw_system_error(ec, "tcp_acceptor::open");
67 }
68
69 void
70 18x tcp_acceptor::assign(native_handle_type fd)
71 {
72 #if BOOST_COROSIO_HAS_IOCP
73 auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
74 #else
75 18x auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
76 #endif
77 18x std::error_code ec = svc.assign_socket(
78 18x *static_cast<tcp_acceptor::implementation*>(h_.get()), fd);
79 18x if (ec)
80 8x detail::throw_system_error(ec, "tcp_acceptor::assign");
81 10x }
82
83 native_handle_type
84 10x tcp_acceptor::release()
85 {
86 10x if (!is_open())
87 2x detail::throw_logic_error("release: acceptor not open");
88 8x return get().release_socket();
89 }
90
91 native_handle_type
92 26x tcp_acceptor::native_handle() const noexcept
93 {
94 26x if (!is_open())
95 {
96 #if BOOST_COROSIO_HAS_IOCP
97 return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
98 #else
99 4x return -1;
100 #endif
101 }
102 22x return get().native_handle();
103 }
104
105 std::error_code
106 401x tcp_acceptor::bind(endpoint ep)
107 {
108 401x if (!is_open())
109 2x detail::throw_logic_error("bind: acceptor not open");
110 #if BOOST_COROSIO_HAS_IOCP
111 auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
112 #else
113 399x auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
114 #endif
115 399x return svc.bind_acceptor(
116 798x *static_cast<tcp_acceptor::implementation*>(h_.get()), ep);
117 }
118
119 std::error_code
120 373x tcp_acceptor::listen(int backlog)
121 {
122 373x if (!is_open())
123 2x detail::throw_logic_error("listen: acceptor not open");
124 #if BOOST_COROSIO_HAS_IOCP
125 auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
126 #else
127 371x auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
128 #endif
129 371x return svc.listen_acceptor(
130 742x *static_cast<tcp_acceptor::implementation*>(h_.get()), backlog);
131 }
132
133 void
134 724x tcp_acceptor::close()
135 {
136 724x if (!is_open())
137 315x return;
138 409x h_.service().close(h_);
139 }
140
141 void
142 11x tcp_acceptor::cancel()
143 {
144 11x if (!is_open())
145 2x return;
146 9x get().cancel();
147 }
148
149 endpoint
150 363x tcp_acceptor::local_endpoint() const noexcept
151 {
152 363x if (!is_open())
153 2x return endpoint{};
154 361x return get().local_endpoint();
155 }
156
157 } // namespace boost::corosio
158