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 make_nonblock_cloexec(fds[0]);
61 make_nonblock_cloexec(fds[1]);
62 #endif
63 14x }
64
65 } // namespace
66
67 std::pair<local_stream_socket, local_stream_socket>
68 8x make_local_stream_pair(io_context& ctx)
69 {
70 int fds[2];
71 8x create_pair(SOCK_STREAM, fds);
72
73 try
74 {
75 8x local_stream_socket s1(ctx);
76 8x local_stream_socket s2(ctx);
77
78 8x s1.assign(fds[0]);
79 8x fds[0] = -1;
80 8x s2.assign(fds[1]);
81 8x fds[1] = -1;
82
83 16x return {std::move(s1), std::move(s2)};
84 8x }
85 catch (...)
86 {
87 if (fds[0] >= 0)
88 ::close(fds[0]);
89 if (fds[1] >= 0)
90 ::close(fds[1]);
91 throw;
92 }
93 }
94
95 std::pair<local_datagram_socket, local_datagram_socket>
96 6x make_local_datagram_pair(io_context& ctx)
97 {
98 int fds[2];
99 6x create_pair(SOCK_DGRAM, fds);
100
101 try
102 {
103 6x local_datagram_socket s1(ctx);
104 6x local_datagram_socket s2(ctx);
105
106 6x s1.assign(fds[0]);
107 6x fds[0] = -1;
108 6x s2.assign(fds[1]);
109 6x fds[1] = -1;
110
111 12x return {std::move(s1), std::move(s2)};
112 6x }
113 catch (...)
114 {
115 if (fds[0] >= 0)
116 ::close(fds[0]);
117 if (fds[1] >= 0)
118 ::close(fds[1]);
119 throw;
120 }
121 }
122
123 } // namespace boost::corosio
124
125 #endif // BOOST_COROSIO_POSIX
126