src/corosio/src/local_socket_pair.cpp

61.0% Lines (25/41) 100.0% List of functions (3/3)
local_socket_pair.cpp
f(x) Functions (3)
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/local_socket_pair.hpp>
11 #include <boost/corosio/io_context.hpp>
12 #include <boost/corosio/detail/platform.hpp>
13
14 #if BOOST_COROSIO_POSIX
15
16 #include <stdexcept>
17 #include <system_error>
18 #include <utility>
19
20 #include <fcntl.h>
21 #include <sys/socket.h>
22 #include <unistd.h>
23
24 namespace boost::corosio {
25
26 namespace {
27
28 #ifndef SOCK_NONBLOCK
29 void
30 make_nonblock_cloexec(int fd)
31 {
32 int fl = ::fcntl(fd, F_GETFL, 0);
33 if (fl < 0)
34 throw std::system_error(
35 std::error_code(errno, std::system_category()),
36 "fcntl(F_GETFL)");
37 if (::fcntl(fd, F_SETFL, fl | O_NONBLOCK) < 0)
38 throw std::system_error(
39 std::error_code(errno, std::system_category()),
40 "fcntl(F_SETFL)");
41 if (::fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
42 throw std::system_error(
43 std::error_code(errno, std::system_category()),
44 "fcntl(F_SETFD)");
45 }
46 #endif
47
48 void
49 14x create_pair(int type, int fds[2])
50 {
51 14x int flags = type;
52 #ifdef SOCK_NONBLOCK
53 14x flags |= SOCK_NONBLOCK | SOCK_CLOEXEC;
54 #endif
55 14x if (::socketpair(AF_UNIX, flags, 0, fds) != 0)
56 throw std::system_error(
57 std::error_code(errno, std::system_category()),
58 "socketpair");
59 #ifndef SOCK_NONBLOCK
60 try
61 {
62 make_nonblock_cloexec(fds[0]);
63 make_nonblock_cloexec(fds[1]);
64 }
65 catch (...)
66 {
67 ::close(fds[0]);
68 ::close(fds[1]);
69 throw;
70 }
71 #endif
72 14x }
73
74 } // namespace
75
76 std::pair<local_stream_socket, local_stream_socket>
77 8x make_local_stream_pair(io_context& ctx)
78 {
79 int fds[2];
80 8x create_pair(SOCK_STREAM, fds);
81
82 try
83 {
84 8x local_stream_socket s1(ctx);
85 8x local_stream_socket s2(ctx);
86
87 8x s1.assign(fds[0]);
88 8x fds[0] = -1;
89 8x s2.assign(fds[1]);
90 8x fds[1] = -1;
91
92 16x return {std::move(s1), std::move(s2)};
93 8x }
94 catch (...)
95 {
96 if (fds[0] >= 0)
97 ::close(fds[0]);
98 if (fds[1] >= 0)
99 ::close(fds[1]);
100 throw;
101 }
102 }
103
104 std::pair<local_datagram_socket, local_datagram_socket>
105 6x make_local_datagram_pair(io_context& ctx)
106 {
107 int fds[2];
108 6x create_pair(SOCK_DGRAM, fds);
109
110 try
111 {
112 6x local_datagram_socket s1(ctx);
113 6x local_datagram_socket s2(ctx);
114
115 6x s1.assign(fds[0]);
116 6x fds[0] = -1;
117 6x s2.assign(fds[1]);
118 6x fds[1] = -1;
119
120 12x return {std::move(s1), std::move(s2)};
121 6x }
122 catch (...)
123 {
124 if (fds[0] >= 0)
125 ::close(fds[0]);
126 if (fds[1] >= 0)
127 ::close(fds[1]);
128 throw;
129 }
130 }
131
132 } // namespace boost::corosio
133
134 #endif // BOOST_COROSIO_POSIX
135