libs/corosio/src/corosio/src/tcp_socket.cpp

76.0% Lines (92/121) 94.7% Functions (18/19) 57.4% Branches (35/61)
libs/corosio/src/corosio/src/tcp_socket.cpp
Line Branch Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
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 #include <boost/corosio/tcp_socket.hpp>
11 #include <boost/corosio/detail/except.hpp>
12 #include <boost/corosio/detail/platform.hpp>
13
14 #if BOOST_COROSIO_HAS_IOCP
15 #include "src/detail/iocp/sockets.hpp"
16 #else
17 // POSIX backends use the abstract socket_service interface
18 #include "src/detail/socket_service.hpp"
19 #endif
20
21 namespace boost::corosio {
22
23 9683 tcp_socket::
24 9683 ~tcp_socket()
25 {
26 9683 close();
27 9683 }
28
29 9503 tcp_socket::
30 tcp_socket(
31 9503 capy::execution_context& ctx)
32 9503 : io_stream(ctx)
33 {
34 9503 }
35
36 void
37 4739 tcp_socket::
38 open()
39 {
40
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4739 times.
4739 if (impl_)
41 return;
42
43 #if BOOST_COROSIO_HAS_IOCP
44 auto& svc = ctx_->use_service<detail::win_sockets>();
45 auto& wrapper = svc.create_impl();
46 impl_ = &wrapper;
47 std::error_code ec = svc.open_socket(*wrapper.get_internal());
48 #else
49 // POSIX backends use abstract socket_service for runtime polymorphism.
50 // The concrete service (epoll_sockets or select_sockets) must be installed
51 // by the context constructor before any socket operations.
52 4739 auto* svc = ctx_->find_service<detail::socket_service>();
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4739 times.
4739 if (!svc)
54 detail::throw_logic_error("tcp_socket::open: no socket service installed");
55
1/1
✓ Branch 1 taken 4739 times.
4739 auto& wrapper = svc->create_impl();
56 4739 impl_ = &wrapper;
57
1/1
✓ Branch 1 taken 4739 times.
4739 std::error_code ec = svc->open_socket(wrapper);
58 #endif
59
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4739 times.
4739 if (ec)
60 {
61 wrapper.release();
62 impl_ = nullptr;
63 detail::throw_system_error(ec, "tcp_socket::open");
64 }
65 }
66
67 void
68 23870 tcp_socket::
69 close()
70 {
71
2/2
✓ Branch 0 taken 14418 times.
✓ Branch 1 taken 9452 times.
23870 if (!impl_)
72 14418 return;
73
74 // socket_impl has virtual release() method
75 9452 impl_->release();
76 9452 impl_ = nullptr;
77 }
78
79 void
80 190 tcp_socket::
81 cancel()
82 {
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 if (!impl_)
84 return;
85 #if BOOST_COROSIO_HAS_IOCP
86 static_cast<detail::win_socket_impl*>(impl_)->get_internal()->cancel();
87 #else
88 // socket_impl has virtual cancel() method
89 190 get().cancel();
90 #endif
91 }
92
93 void
94 12 tcp_socket::
95 shutdown(shutdown_type what)
96 {
97
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (impl_)
98 6 get().shutdown(what);
99 12 }
100
101 native_handle_type
102 tcp_socket::
103 native_handle() const noexcept
104 {
105 if (!impl_)
106 {
107 #if BOOST_COROSIO_HAS_IOCP
108 return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
109 #else
110 return -1;
111 #endif
112 }
113 return get().native_handle();
114 }
115
116 //------------------------------------------------------------------------------
117 // Socket Options
118 //------------------------------------------------------------------------------
119
120 void
121 10 tcp_socket::
122 set_no_delay(bool value)
123 {
124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!impl_)
125 detail::throw_logic_error("set_no_delay: socket not open");
126 10 std::error_code ec = get().set_no_delay(value);
127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (ec)
128 detail::throw_system_error(ec, "tcp_socket::set_no_delay");
129 10 }
130
131 bool
132 10 tcp_socket::
133 no_delay() const
134 {
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!impl_)
136 detail::throw_logic_error("no_delay: socket not open");
137 10 std::error_code ec;
138 10 bool result = get().no_delay(ec);
139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (ec)
140 detail::throw_system_error(ec, "tcp_socket::no_delay");
141 10 return result;
142 }
143
144 void
145 8 tcp_socket::
146 set_keep_alive(bool value)
147 {
148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!impl_)
149 detail::throw_logic_error("set_keep_alive: socket not open");
150 8 std::error_code ec = get().set_keep_alive(value);
151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (ec)
152 detail::throw_system_error(ec, "tcp_socket::set_keep_alive");
153 8 }
154
155 bool
156 8 tcp_socket::
157 keep_alive() const
158 {
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!impl_)
160 detail::throw_logic_error("keep_alive: socket not open");
161 8 std::error_code ec;
162 8 bool result = get().keep_alive(ec);
163
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (ec)
164 detail::throw_system_error(ec, "tcp_socket::keep_alive");
165 8 return result;
166 }
167
168 void
169 2 tcp_socket::
170 set_receive_buffer_size(int size)
171 {
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!impl_)
173 detail::throw_logic_error("set_receive_buffer_size: socket not open");
174 2 std::error_code ec = get().set_receive_buffer_size(size);
175
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (ec)
176 detail::throw_system_error(ec, "tcp_socket::set_receive_buffer_size");
177 2 }
178
179 int
180 6 tcp_socket::
181 receive_buffer_size() const
182 {
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!impl_)
184 detail::throw_logic_error("receive_buffer_size: socket not open");
185 6 std::error_code ec;
186 6 int result = get().receive_buffer_size(ec);
187
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (ec)
188 detail::throw_system_error(ec, "tcp_socket::receive_buffer_size");
189 6 return result;
190 }
191
192 void
193 2 tcp_socket::
194 set_send_buffer_size(int size)
195 {
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!impl_)
197 detail::throw_logic_error("set_send_buffer_size: socket not open");
198 2 std::error_code ec = get().set_send_buffer_size(size);
199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (ec)
200 detail::throw_system_error(ec, "tcp_socket::set_send_buffer_size");
201 2 }
202
203 int
204 6 tcp_socket::
205 send_buffer_size() const
206 {
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!impl_)
208 detail::throw_logic_error("send_buffer_size: socket not open");
209 6 std::error_code ec;
210 6 int result = get().send_buffer_size(ec);
211
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (ec)
212 detail::throw_system_error(ec, "tcp_socket::send_buffer_size");
213 6 return result;
214 }
215
216 void
217 8 tcp_socket::
218 set_linger(bool enabled, int timeout)
219 {
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!impl_)
221 detail::throw_logic_error("set_linger: socket not open");
222 8 std::error_code ec = get().set_linger(enabled, timeout);
223
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
8 if (ec)
224 2 detail::throw_system_error(ec, "tcp_socket::set_linger");
225 6 }
226
227 tcp_socket::linger_options
228 6 tcp_socket::
229 linger() const
230 {
231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!impl_)
232 detail::throw_logic_error("linger: socket not open");
233 6 std::error_code ec;
234 6 linger_options result = get().linger(ec);
235
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (ec)
236 detail::throw_system_error(ec, "tcp_socket::linger");
237 6 return result;
238 }
239
240 endpoint
241 42 tcp_socket::
242 local_endpoint() const noexcept
243 {
244
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 32 times.
42 if (!impl_)
245 10 return endpoint{};
246 32 return get().local_endpoint();
247 }
248
249 endpoint
250 42 tcp_socket::
251 remote_endpoint() const noexcept
252 {
253
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 32 times.
42 if (!impl_)
254 10 return endpoint{};
255 32 return get().remote_endpoint();
256 }
257
258 } // namespace boost::corosio
259