src/corosio/src/detail/open_listener.hpp

87.5% Lines (7 / 8) 100.0% Functions (1 / 1)
open_listener.hpp
f(x) Functions (1)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_SRC_DETAIL_OPEN_LISTENER_HPP
11 #define BOOST_COROSIO_SRC_DETAIL_OPEN_LISTENER_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14 #include <boost/corosio/endpoint.hpp>
15 #include <boost/corosio/socket_option.hpp>
16 #include <boost/corosio/tcp_acceptor.hpp>
17
18 #if BOOST_COROSIO_HAS_IOCP
19 #include <boost/corosio/native/detail/iocp/win_windows.hpp>
20 #endif
21
22 #include <cstddef>
23 #include <system_error>
24
25 namespace boost::corosio::detail {
26
27 #if BOOST_COROSIO_HAS_IOCP
28 // On Windows SO_REUSEADDR grants bind-over ("hijack") rights instead
29 // of TIME_WAIT reuse, so a second listener would share the port
30 // silently. SO_EXCLUSIVEADDRUSE restores the POSIX contract: the
31 // collision surfaces as WSAEADDRINUSE (errc::address_in_use).
32 struct exclusive_address_use
33 {
34 int value_ = 1;
35
36 static int level(family) noexcept
37 {
38 return SOL_SOCKET;
39 }
40 static int name(family) noexcept
41 {
42 return SO_EXCLUSIVEADDRUSE;
43 }
44 void const* data(family) const noexcept
45 {
46 return &value_;
47 }
48 std::size_t size(family) const noexcept
49 {
50 return sizeof(value_);
51 }
52 };
53 #endif
54
55 // Open, configure address reuse, bind and listen, stopping at the
56 // first failing step.
57 inline std::error_code
58 204x open_listener(tcp_acceptor& acc, endpoint ep, int backlog) noexcept
59 {
60 204x if (auto ec = acc.open(ep.address().family()))
61 2x return ec;
62 #if BOOST_COROSIO_HAS_IOCP
63 if (auto ec = acc.set_option(exclusive_address_use{}))
64 return ec;
65 #else
66 202x if (auto ec = acc.set_option(socket_option::reuse_address(true)))
67 ✗ return ec;
68 #endif
69 202x if (auto ec = acc.bind(ep))
70 8x return ec;
71 194x return acc.listen(backlog);
72 }
73
74 } // namespace boost::corosio::detail
75
76 #endif
77