src/corosio/src/local_datagram_socket.cpp

43.2% Lines (32/74) 46.7% List of functions (7/15)
local_datagram_socket.cpp
f(x) Functions (15)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Michael Vandeberg
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/detail/platform.hpp>
11
12 #if BOOST_COROSIO_POSIX || BOOST_COROSIO_HAS_IOCP
13
14 #include <boost/corosio/local_datagram_socket.hpp>
15 #include <boost/corosio/detail/except.hpp>
16 #include <boost/corosio/detail/local_datagram_service.hpp>
17
18 #if BOOST_COROSIO_POSIX
19 #include <sys/ioctl.h>
20 #elif BOOST_COROSIO_HAS_IOCP
21 #include <boost/corosio/native/detail/iocp/win_windows.hpp>
22 #endif
23
24 namespace boost::corosio {
25
26 48x local_datagram_socket::~local_datagram_socket()
27 {
28 48x close();
29 48x }
30
31 34x local_datagram_socket::local_datagram_socket(capy::execution_context& ctx)
32 34x : io_object(create_handle<detail::local_datagram_service>(ctx))
33 {
34 34x }
35
36 void
37 20x local_datagram_socket::open(local_datagram proto)
38 {
39 20x if (is_open())
40 return;
41 20x open_for_family(proto.family(), proto.type(), proto.protocol());
42 }
43
44 void
45 20x local_datagram_socket::open_for_family(int family, int type, int protocol)
46 {
47 20x auto& svc = static_cast<detail::local_datagram_service&>(h_.service());
48 20x std::error_code ec = svc.open_socket(
49 20x static_cast<local_datagram_socket::implementation&>(*h_.get()),
50 family, type, protocol);
51 20x if (ec)
52 detail::throw_system_error(ec, "local_datagram_socket::open");
53 20x }
54
55 void
56 50x local_datagram_socket::close()
57 {
58 50x if (!is_open())
59 18x return;
60 32x h_.service().close(h_);
61 }
62
63 std::error_code
64 16x local_datagram_socket::bind(corosio::local_endpoint ep)
65 {
66 16x if (!is_open())
67 detail::throw_logic_error("bind: socket not open");
68 16x auto& svc = static_cast<detail::local_datagram_service&>(h_.service());
69 16x return svc.bind_socket(
70 16x static_cast<local_datagram_socket::implementation&>(*h_.get()),
71 16x ep);
72 }
73
74 void
75 local_datagram_socket::cancel()
76 {
77 if (!is_open())
78 return;
79 get().cancel();
80 }
81
82 void
83 local_datagram_socket::shutdown(shutdown_type what)
84 {
85 if (is_open())
86 {
87 // Best-effort: errors like ENOTCONN are expected and unhelpful
88 [[maybe_unused]] auto ec = get().shutdown(what);
89 }
90 }
91
92 void
93 local_datagram_socket::shutdown(shutdown_type what, std::error_code& ec) noexcept
94 {
95 ec = {};
96 if (is_open())
97 ec = get().shutdown(what);
98 }
99
100 void
101 12x local_datagram_socket::assign(int fd)
102 {
103 12x if (is_open())
104 detail::throw_logic_error("assign: socket already open");
105 12x auto& svc = static_cast<detail::local_datagram_service&>(h_.service());
106 12x std::error_code ec = svc.assign_socket(
107 12x static_cast<local_datagram_socket::implementation&>(*h_.get()), fd);
108 12x if (ec)
109 detail::throw_system_error(ec, "local_datagram_socket::assign");
110 12x }
111
112 native_handle_type
113 local_datagram_socket::native_handle() const noexcept
114 {
115 if (!is_open())
116 #if BOOST_COROSIO_HAS_IOCP
117 return ~native_handle_type(0);
118 #else
119 return -1;
120 #endif
121 return get().native_handle();
122 }
123
124 native_handle_type
125 local_datagram_socket::release()
126 {
127 if (!is_open())
128 detail::throw_logic_error("release: socket not open");
129 return get().release_socket();
130 }
131
132 std::size_t
133 local_datagram_socket::available() const
134 {
135 if (!is_open())
136 detail::throw_logic_error("available: socket not open");
137 #if BOOST_COROSIO_HAS_IOCP
138 u_long value = 0;
139 if (::ioctlsocket(
140 static_cast<SOCKET>(native_handle()), FIONREAD, &value) != 0)
141 detail::throw_system_error(
142 std::error_code(::WSAGetLastError(), std::system_category()),
143 "local_datagram_socket::available");
144 return static_cast<std::size_t>(value);
145 #else
146 int value = 0;
147 if (::ioctl(native_handle(), FIONREAD, &value) < 0)
148 detail::throw_system_error(
149 std::error_code(errno, std::system_category()),
150 "local_datagram_socket::available");
151 return static_cast<std::size_t>(value);
152 #endif
153 }
154
155 local_endpoint
156 local_datagram_socket::local_endpoint() const noexcept
157 {
158 if (!is_open())
159 return corosio::local_endpoint{};
160 return get().local_endpoint();
161 }
162
163 local_endpoint
164 local_datagram_socket::remote_endpoint() const noexcept
165 {
166 if (!is_open())
167 return corosio::local_endpoint{};
168 return get().remote_endpoint();
169 }
170
171 } // namespace boost::corosio
172
173 #endif // BOOST_COROSIO_POSIX || BOOST_COROSIO_HAS_IOCP
174