src/corosio/src/local_datagram_socket.cpp

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