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