TLA Line data 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 : #ifndef BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_TRAITS_HPP
11 : #define BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_TRAITS_HPP
12 :
13 : #include <boost/corosio/detail/platform.hpp>
14 :
15 : #if BOOST_COROSIO_HAS_EPOLL
16 :
17 : #include <boost/corosio/native/detail/make_err.hpp>
18 : #include <boost/corosio/native/detail/reactor/reactor_descriptor_state.hpp>
19 :
20 : #include <system_error>
21 :
22 : #include <errno.h>
23 : #include <netinet/in.h>
24 : #include <sys/socket.h>
25 :
26 : /* epoll backend traits.
27 :
28 : Captures the platform-specific behavior of the Linux epoll backend:
29 : atomic SOCK_NONBLOCK|SOCK_CLOEXEC on socket(), accept4() for
30 : accepted connections, and sendmsg(MSG_NOSIGNAL) for writes.
31 : */
32 :
33 : namespace boost::corosio::detail {
34 :
35 : class epoll_scheduler;
36 : struct descriptor_state;
37 :
38 : struct epoll_traits
39 : {
40 : using scheduler_type = epoll_scheduler;
41 : using desc_state_type = descriptor_state;
42 :
43 : static constexpr bool needs_write_notification = false;
44 :
45 : /// No extra per-socket state or lifecycle hooks needed for epoll.
46 : struct stream_socket_hook
47 : {
48 HIT 32 : std::error_code on_set_option(
49 : int fd, int level, int optname,
50 : void const* data, std::size_t size) noexcept
51 : {
52 32 : if (::setsockopt(
53 : fd, level, optname, data,
54 32 : static_cast<socklen_t>(size)) != 0)
55 MIS 0 : return make_err(errno);
56 HIT 32 : return {};
57 : }
58 41011 : static void pre_shutdown(int) noexcept {}
59 13659 : static void pre_destroy(int) noexcept {}
60 : };
61 :
62 : struct write_policy
63 : {
64 94147 : static ssize_t write(int fd, iovec* iovecs, int count) noexcept
65 : {
66 94147 : msghdr msg{};
67 94147 : msg.msg_iov = iovecs;
68 94147 : msg.msg_iovlen = static_cast<std::size_t>(count);
69 :
70 : ssize_t n;
71 : do
72 : {
73 94147 : n = ::sendmsg(fd, &msg, MSG_NOSIGNAL);
74 : }
75 94147 : while (n < 0 && errno == EINTR);
76 94147 : return n;
77 : }
78 : };
79 :
80 : struct accept_policy
81 : {
82 9070 : static int do_accept(
83 : int fd, sockaddr_storage& peer, socklen_t& addrlen) noexcept
84 : {
85 9070 : addrlen = sizeof(peer);
86 : int new_fd;
87 : do
88 : {
89 9070 : new_fd = ::accept4(
90 : fd, reinterpret_cast<sockaddr*>(&peer), &addrlen,
91 : SOCK_NONBLOCK | SOCK_CLOEXEC);
92 : }
93 9070 : while (new_fd < 0 && errno == EINTR);
94 9070 : return new_fd;
95 : }
96 : };
97 :
98 : /// Create a nonblocking, close-on-exec socket using Linux's atomic flags.
99 4697 : static int create_socket(int family, int type, int protocol) noexcept
100 : {
101 4697 : return ::socket(family, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol);
102 : }
103 :
104 : /// Apply protocol-specific options after socket creation.
105 : /// For IP sockets, sets IPV6_V6ONLY on AF_INET6.
106 : static std::error_code
107 4594 : configure_ip_socket(int fd, int family) noexcept
108 : {
109 4594 : if (family == AF_INET6)
110 : {
111 13 : int one = 1;
112 13 : if (::setsockopt(
113 13 : fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)) != 0)
114 MIS 0 : return make_err(errno);
115 : }
116 HIT 4594 : return {};
117 : }
118 :
119 : /// Apply protocol-specific options for acceptor sockets.
120 : /// For IP acceptors, sets IPV6_V6ONLY=0 (dual-stack).
121 : static std::error_code
122 83 : configure_ip_acceptor(int fd, int family) noexcept
123 : {
124 83 : if (family == AF_INET6)
125 : {
126 8 : int val = 0;
127 8 : if (::setsockopt(
128 8 : fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)) != 0)
129 MIS 0 : return make_err(errno);
130 : }
131 HIT 83 : return {};
132 : }
133 :
134 : /// No extra configuration needed for local (unix) sockets on epoll.
135 : static std::error_code
136 36 : configure_local_socket(int /*fd*/) noexcept
137 : {
138 36 : return {};
139 : }
140 : };
141 :
142 : } // namespace boost::corosio::detail
143 :
144 : #endif // BOOST_COROSIO_HAS_EPOLL
145 :
146 : #endif // BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_TRAITS_HPP
|