src/corosio/src/tcp_socket.cpp

100.0% Lines (59 / 59) 100.0% Functions (13 / 13)
tcp_socket.cpp
f(x) Functions (13)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco ([email protected])
3 // Copyright (c) 2026 Steve Gerbino
4 // Copyright (c) 2026 Michael Vandeberg
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // Official repository: https://github.com/cppalliance/corosio
10 //
11
12 #include <boost/corosio/tcp_socket.hpp>
13 #include <boost/corosio/error.hpp>
14 #include <boost/corosio/native/detail/endpoint_convert.hpp>
15 #include <boost/corosio/detail/except.hpp>
16 #include <boost/corosio/detail/platform.hpp>
17
18 #include "src/detail/use_backend_service.hpp"
19
20 #if BOOST_COROSIO_HAS_IOCP
21 #include <boost/corosio/native/detail/iocp/win_tcp_acceptor_service.hpp>
22 #else
23 #include <boost/corosio/detail/tcp_service.hpp>
24 #endif
25
26 namespace boost::corosio {
27
28 namespace {
29
30 #if BOOST_COROSIO_HAS_IOCP
31 using tcp_service_key = detail::win_tcp_service;
32 #else
33 using tcp_service_key = detail::tcp_service;
34 #endif
35
36 } // namespace
37
38 21102x tcp_socket::~tcp_socket()
39 {
40 21078x close();
41 21102x }
42
43 17536x tcp_socket::tcp_socket(capy::execution_context& ctx)
44 17536x : io_object(handle(
45 ctx,
46 17536x detail::use_backend_service<detail::tcp_service_of, tcp_service_key>(
47 52608x ctx)))
48 {
49 17536x }
50
51 std::error_code
52 8604x tcp_socket::open(family f) noexcept
53 {
54 8604x if (is_open())
55 6x return {};
56 8598x return open_for_family(detail::native_family(f), SOCK_STREAM, IPPROTO_TCP);
57 }
58
59 std::error_code
60 8598x tcp_socket::open_for_family(int family, int type, int protocol) noexcept
61 {
62 #if BOOST_COROSIO_HAS_IOCP
63 auto& svc = static_cast<detail::win_tcp_service&>(h_.service());
64 auto& wrapper = static_cast<tcp_socket::implementation&>(*h_.get());
65 std::error_code ec = svc.open_socket(
66 *static_cast<detail::win_tcp_socket&>(wrapper).get_internal(), family,
67 type, protocol);
68 #else
69 8598x auto& svc = static_cast<detail::tcp_service&>(h_.service());
70 8598x std::error_code ec = svc.open_socket(
71 8598x static_cast<tcp_socket::implementation&>(*h_.get()), family, type,
72 protocol);
73 #endif
74 8598x return ec;
75 }
76
77 std::error_code
78 49x tcp_socket::assign(native_handle_type fd) noexcept
79 {
80 49x if (is_open())
81 12x return make_error_code(error::already_open);
82 #if BOOST_COROSIO_HAS_IOCP
83 auto& svc = static_cast<detail::win_tcp_service&>(h_.service());
84 auto& wrapper = static_cast<tcp_socket::implementation&>(*h_.get());
85 std::error_code ec = svc.assign_socket(
86 *static_cast<detail::win_tcp_socket&>(wrapper).get_internal(), fd);
87 #else
88 37x auto& svc = static_cast<detail::tcp_service&>(h_.service());
89 37x std::error_code ec = svc.assign_socket(
90 37x static_cast<tcp_socket::implementation&>(*h_.get()), fd);
91 #endif
92 37x return ec;
93 }
94
95 native_handle_type
96 8x tcp_socket::release()
97 {
98 8x if (!is_open())
99 3x detail::throw_system_error(
100 3x make_error_code(std::errc::bad_file_descriptor),
101 "tcp_socket::release");
102 5x return get().release_socket();
103 }
104
105 std::error_code
106 33x tcp_socket::bind(endpoint ep) noexcept
107 {
108 33x if (!is_open())
109 3x return make_error_code(std::errc::bad_file_descriptor);
110 #if BOOST_COROSIO_HAS_IOCP
111 auto& svc = static_cast<detail::win_tcp_service&>(h_.service());
112 auto& wrapper = static_cast<tcp_socket::implementation&>(*h_.get());
113 return svc.bind_socket(
114 *static_cast<detail::win_tcp_socket&>(wrapper).get_internal(), ep);
115 #else
116 30x auto& svc = static_cast<detail::tcp_service&>(h_.service());
117 30x return svc.bind_socket(
118 60x static_cast<tcp_socket::implementation&>(*h_.get()), ep);
119 #endif
120 }
121
122 void
123 38106x tcp_socket::close() noexcept
124 {
125 38106x if (!is_open())
126 21122x return;
127 16984x h_.service().close(h_);
128 }
129
130 void
131 353x tcp_socket::cancel() noexcept
132 {
133 353x if (!is_open())
134 3x return;
135 350x get().cancel();
136 }
137
138 std::error_code
139 35x tcp_socket::shutdown(shutdown_type what) noexcept
140 {
141 35x if (!is_open())
142 9x return make_error_code(std::errc::bad_file_descriptor);
143 26x return get().shutdown(what);
144 }
145
146 native_handle_type
147 191x tcp_socket::native_handle() const noexcept
148 {
149 191x if (!is_open())
150 {
151 #if BOOST_COROSIO_HAS_IOCP
152 return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
153 #else
154 3x return -1;
155 #endif
156 }
157 188x return get().native_handle();
158 }
159
160 endpoint
161 102x tcp_socket::local_endpoint() const noexcept
162 {
163 102x if (!is_open())
164 15x return endpoint{};
165 87x return get().local_endpoint();
166 }
167
168 endpoint
169 103x tcp_socket::remote_endpoint() const noexcept
170 {
171 103x if (!is_open())
172 15x return endpoint{};
173 88x return get().remote_endpoint();
174 }
175
176 } // namespace boost::corosio
177