src/corosio/src/local_socket_pair.cpp

58.1% Lines (25/43) 75.0% List of functions (3/4)
local_socket_pair.cpp
f(x) Functions (4)
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 void
29 make_nonblock_cloexec(int fd)
30 {
31 #ifndef SOCK_NONBLOCK
32 int fl = ::fcntl(fd, F_GETFL, 0);
33 ::fcntl(fd, F_SETFL, fl | O_NONBLOCK);
34 ::fcntl(fd, F_SETFD, FD_CLOEXEC);
35 #else
36 (void)fd;
37 #endif
38 }
39
40 void
41 14x create_pair(int type, int fds[2])
42 {
43 14x int flags = type;
44 #ifdef SOCK_NONBLOCK
45 14x flags |= SOCK_NONBLOCK | SOCK_CLOEXEC;
46 #endif
47 14x if (::socketpair(AF_UNIX, flags, 0, fds) != 0)
48 throw std::system_error(
49 std::error_code(errno, std::system_category()),
50 "socketpair");
51 #ifndef SOCK_NONBLOCK
52 make_nonblock_cloexec(fds[0]);
53 make_nonblock_cloexec(fds[1]);
54 #endif
55 14x }
56
57 } // namespace
58
59 std::pair<local_stream_socket, local_stream_socket>
60 8x make_local_stream_pair(io_context& ctx)
61 {
62 int fds[2];
63 8x create_pair(SOCK_STREAM, fds);
64
65 try
66 {
67 8x local_stream_socket s1(ctx);
68 8x local_stream_socket s2(ctx);
69
70 8x s1.assign(fds[0]);
71 8x fds[0] = -1;
72 8x s2.assign(fds[1]);
73 8x fds[1] = -1;
74
75 16x return {std::move(s1), std::move(s2)};
76 8x }
77 catch (...)
78 {
79 if (fds[0] >= 0)
80 ::close(fds[0]);
81 if (fds[1] >= 0)
82 ::close(fds[1]);
83 throw;
84 }
85 }
86
87 std::pair<local_datagram_socket, local_datagram_socket>
88 6x make_local_datagram_pair(io_context& ctx)
89 {
90 int fds[2];
91 6x create_pair(SOCK_DGRAM, fds);
92
93 try
94 {
95 6x local_datagram_socket s1(ctx);
96 6x local_datagram_socket s2(ctx);
97
98 6x s1.assign(fds[0]);
99 6x fds[0] = -1;
100 6x s2.assign(fds[1]);
101 6x fds[1] = -1;
102
103 12x return {std::move(s1), std::move(s2)};
104 6x }
105 catch (...)
106 {
107 if (fds[0] >= 0)
108 ::close(fds[0]);
109 if (fds[1] >= 0)
110 ::close(fds[1]);
111 throw;
112 }
113 }
114
115 } // namespace boost::corosio
116
117 #endif // BOOST_COROSIO_POSIX
118