src/corosio/src/tcp_socket.cpp

98.3% Lines (57/0/58) 100.0% List of functions (13/0/13)
tcp_socket.cpp
f(x) Functions (13)
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_socket.hpp>
12 #include <boost/corosio/detail/except.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_service.hpp>
19 #endif
20
21 namespace boost::corosio {
22
23 9479x tcp_socket::~tcp_socket()
24 {
25 9479x close();
26 9479x }
27
28 8958x tcp_socket::tcp_socket(capy::execution_context& ctx)
29 #if BOOST_COROSIO_HAS_IOCP
30 : io_object(create_handle<detail::win_tcp_service>(ctx))
31 #else
32 8958x : io_object(create_handle<detail::tcp_service>(ctx))
33 #endif
34 {
35 8958x }
36
37 void
38 4448x tcp_socket::open(tcp proto)
39 {
40 4448x if (is_open())
41 2x return;
42 4446x open_for_family(proto.family(), proto.type(), proto.protocol());
43 }
44
45 void
46 4446x tcp_socket::open_for_family(int family, int type, int protocol)
47 {
48 #if BOOST_COROSIO_HAS_IOCP
49 auto& svc = static_cast<detail::win_tcp_service&>(h_.service());
50 auto& wrapper = static_cast<tcp_socket::implementation&>(*h_.get());
51 std::error_code ec = svc.open_socket(
52 *static_cast<detail::win_tcp_socket&>(wrapper).get_internal(), family, type,
53 protocol);
54 #else
55 4446x auto& svc = static_cast<detail::tcp_service&>(h_.service());
56 4446x std::error_code ec = svc.open_socket(
57 4446x static_cast<tcp_socket::implementation&>(*h_.get()), family, type,
58 protocol);
59 #endif
60 4446x if (ec)
61 detail::throw_system_error(ec, "tcp_socket::open");
62 4446x }
63
64 void
65 16x tcp_socket::assign(native_handle_type fd)
66 {
67 #if BOOST_COROSIO_HAS_IOCP
68 auto& svc = static_cast<detail::win_tcp_service&>(h_.service());
69 auto& wrapper = static_cast<tcp_socket::implementation&>(*h_.get());
70 std::error_code ec = svc.assign_socket(
71 *static_cast<detail::win_tcp_socket&>(wrapper).get_internal(), fd);
72 #else
73 16x auto& svc = static_cast<detail::tcp_service&>(h_.service());
74 16x std::error_code ec = svc.assign_socket(
75 16x static_cast<tcp_socket::implementation&>(*h_.get()), fd);
76 #endif
77 16x if (ec)
78 10x detail::throw_system_error(ec, "tcp_socket::assign");
79 6x }
80
81 native_handle_type
82 4x tcp_socket::release()
83 {
84 4x if (!is_open())
85 2x detail::throw_logic_error("release: socket not open");
86 2x return get().release_socket();
87 }
88
89 std::error_code
90 16x tcp_socket::bind(endpoint ep)
91 {
92 16x if (!is_open())
93 2x detail::throw_logic_error("bind: socket not open");
94 #if BOOST_COROSIO_HAS_IOCP
95 auto& svc = static_cast<detail::win_tcp_service&>(h_.service());
96 auto& wrapper = static_cast<tcp_socket::implementation&>(*h_.get());
97 return svc.bind_socket(
98 *static_cast<detail::win_tcp_socket&>(wrapper).get_internal(), ep);
99 #else
100 14x auto& svc = static_cast<detail::tcp_service&>(h_.service());
101 14x return svc.bind_socket(
102 28x static_cast<tcp_socket::implementation&>(*h_.get()), ep);
103 #endif
104 }
105
106 void
107 18034x tcp_socket::close()
108 {
109 18034x if (!is_open())
110 9218x return;
111 8816x h_.service().close(h_);
112 }
113
114 void
115 203x tcp_socket::cancel()
116 {
117 203x if (!is_open())
118 2x return;
119 201x get().cancel();
120 }
121
122 void
123 25x tcp_socket::shutdown(shutdown_type what)
124 {
125 25x if (is_open())
126 {
127 // Best-effort: errors like ENOTCONN are expected and unhelpful
128 19x [[maybe_unused]] auto ec = get().shutdown(what);
129 }
130 25x }
131
132 native_handle_type
133 34x tcp_socket::native_handle() const noexcept
134 {
135 34x if (!is_open())
136 {
137 #if BOOST_COROSIO_HAS_IOCP
138 return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
139 #else
140 2x return -1;
141 #endif
142 }
143 32x return get().native_handle();
144 }
145
146 endpoint
147 68x tcp_socket::local_endpoint() const noexcept
148 {
149 68x if (!is_open())
150 10x return endpoint{};
151 58x return get().local_endpoint();
152 }
153
154 endpoint
155 66x tcp_socket::remote_endpoint() const noexcept
156 {
157 66x if (!is_open())
158 10x return endpoint{};
159 56x return get().remote_endpoint();
160 }
161
162 } // namespace boost::corosio
163