1 | //===-- llvm/Support/raw_socket_stream.cpp - Socket streams --*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains raw_ostream implementations for streams to communicate |
10 | // via UNIX sockets |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/Support/raw_socket_stream.h" |
15 | #include "llvm/Config/config.h" |
16 | #include "llvm/Support/Error.h" |
17 | |
18 | #ifndef _WIN32 |
19 | #include <sys/socket.h> |
20 | #include <sys/un.h> |
21 | #else |
22 | #include "llvm/Support/Windows/WindowsSupport.h" |
23 | // winsock2.h must be included before afunix.h. Briefly turn off clang-format to |
24 | // avoid error. |
25 | // clang-format off |
26 | #include <winsock2.h> |
27 | #include <afunix.h> |
28 | // clang-format on |
29 | #include <io.h> |
30 | #endif // _WIN32 |
31 | |
32 | #if defined(HAVE_UNISTD_H) |
33 | #include <unistd.h> |
34 | #endif |
35 | |
36 | using namespace llvm; |
37 | |
38 | #ifdef _WIN32 |
39 | WSABalancer::WSABalancer() { |
40 | WSADATA WsaData; |
41 | ::memset(&WsaData, 0, sizeof(WsaData)); |
42 | if (WSAStartup(MAKEWORD(2, 2), &WsaData) != 0) { |
43 | llvm::report_fatal_error("WSAStartup failed" ); |
44 | } |
45 | } |
46 | |
47 | WSABalancer::~WSABalancer() { WSACleanup(); } |
48 | |
49 | #endif // _WIN32 |
50 | |
51 | static std::error_code getLastSocketErrorCode() { |
52 | #ifdef _WIN32 |
53 | return std::error_code(::WSAGetLastError(), std::system_category()); |
54 | #else |
55 | return std::error_code(errno, std::system_category()); |
56 | #endif |
57 | } |
58 | |
59 | ListeningSocket::ListeningSocket(int SocketFD, StringRef SocketPath) |
60 | : FD(SocketFD), SocketPath(SocketPath) {} |
61 | |
62 | ListeningSocket::ListeningSocket(ListeningSocket &&LS) |
63 | : FD(LS.FD), SocketPath(LS.SocketPath) { |
64 | LS.FD = -1; |
65 | } |
66 | |
67 | Expected<ListeningSocket> ListeningSocket::createUnix(StringRef SocketPath, |
68 | int MaxBacklog) { |
69 | |
70 | #ifdef _WIN32 |
71 | WSABalancer _; |
72 | SOCKET MaybeWinsocket = socket(AF_UNIX, SOCK_STREAM, 0); |
73 | if (MaybeWinsocket == INVALID_SOCKET) { |
74 | #else |
75 | int MaybeWinsocket = socket(AF_UNIX, SOCK_STREAM, protocol: 0); |
76 | if (MaybeWinsocket == -1) { |
77 | #endif |
78 | return llvm::make_error<StringError>(Args: getLastSocketErrorCode(), |
79 | Args: "socket create failed" ); |
80 | } |
81 | |
82 | struct sockaddr_un Addr; |
83 | memset(s: &Addr, c: 0, n: sizeof(Addr)); |
84 | Addr.sun_family = AF_UNIX; |
85 | strncpy(dest: Addr.sun_path, src: SocketPath.str().c_str(), n: sizeof(Addr.sun_path) - 1); |
86 | |
87 | if (bind(fd: MaybeWinsocket, addr: (struct sockaddr *)&Addr, len: sizeof(Addr)) == -1) { |
88 | std::error_code Err = getLastSocketErrorCode(); |
89 | if (Err == std::errc::address_in_use) |
90 | ::close(fd: MaybeWinsocket); |
91 | return llvm::make_error<StringError>(Args&: Err, Args: "Bind error" ); |
92 | } |
93 | if (listen(fd: MaybeWinsocket, n: MaxBacklog) == -1) { |
94 | return llvm::make_error<StringError>(Args: getLastSocketErrorCode(), |
95 | Args: "Listen error" ); |
96 | } |
97 | int UnixSocket; |
98 | #ifdef _WIN32 |
99 | UnixSocket = _open_osfhandle(MaybeWinsocket, 0); |
100 | #else |
101 | UnixSocket = MaybeWinsocket; |
102 | #endif // _WIN32 |
103 | return ListeningSocket{UnixSocket, SocketPath}; |
104 | } |
105 | |
106 | Expected<std::unique_ptr<raw_socket_stream>> ListeningSocket::accept() { |
107 | int AcceptFD; |
108 | #ifdef _WIN32 |
109 | SOCKET WinServerSock = _get_osfhandle(FD); |
110 | SOCKET WinAcceptSock = ::accept(WinServerSock, NULL, NULL); |
111 | AcceptFD = _open_osfhandle(WinAcceptSock, 0); |
112 | #else |
113 | AcceptFD = ::accept(fd: FD, NULL, NULL); |
114 | #endif //_WIN32 |
115 | if (AcceptFD == -1) |
116 | return llvm::make_error<StringError>(Args: getLastSocketErrorCode(), |
117 | Args: "Accept failed" ); |
118 | return std::make_unique<raw_socket_stream>(args&: AcceptFD); |
119 | } |
120 | |
121 | ListeningSocket::~ListeningSocket() { |
122 | if (FD == -1) |
123 | return; |
124 | ::close(fd: FD); |
125 | unlink(name: SocketPath.c_str()); |
126 | } |
127 | |
128 | static Expected<int> GetSocketFD(StringRef SocketPath) { |
129 | #ifdef _WIN32 |
130 | SOCKET MaybeWinsocket = socket(AF_UNIX, SOCK_STREAM, 0); |
131 | if (MaybeWinsocket == INVALID_SOCKET) { |
132 | #else |
133 | int MaybeWinsocket = socket(AF_UNIX, SOCK_STREAM, protocol: 0); |
134 | if (MaybeWinsocket == -1) { |
135 | #endif // _WIN32 |
136 | return llvm::make_error<StringError>(Args: getLastSocketErrorCode(), |
137 | Args: "Create socket failed" ); |
138 | } |
139 | |
140 | struct sockaddr_un Addr; |
141 | memset(s: &Addr, c: 0, n: sizeof(Addr)); |
142 | Addr.sun_family = AF_UNIX; |
143 | strncpy(dest: Addr.sun_path, src: SocketPath.str().c_str(), n: sizeof(Addr.sun_path) - 1); |
144 | |
145 | int status = connect(fd: MaybeWinsocket, addr: (struct sockaddr *)&Addr, len: sizeof(Addr)); |
146 | if (status == -1) { |
147 | return llvm::make_error<StringError>(Args: getLastSocketErrorCode(), |
148 | Args: "Connect socket failed" ); |
149 | } |
150 | #ifdef _WIN32 |
151 | return _open_osfhandle(MaybeWinsocket, 0); |
152 | #else |
153 | return MaybeWinsocket; |
154 | #endif // _WIN32 |
155 | } |
156 | |
157 | raw_socket_stream::raw_socket_stream(int SocketFD) |
158 | : raw_fd_stream(SocketFD, true) {} |
159 | |
160 | Expected<std::unique_ptr<raw_socket_stream>> |
161 | raw_socket_stream::createConnectedUnix(StringRef SocketPath) { |
162 | #ifdef _WIN32 |
163 | WSABalancer _; |
164 | #endif // _WIN32 |
165 | Expected<int> FD = GetSocketFD(SocketPath); |
166 | if (!FD) |
167 | return FD.takeError(); |
168 | return std::make_unique<raw_socket_stream>(args&: *FD); |
169 | } |
170 | |
171 | raw_socket_stream::~raw_socket_stream() {} |
172 | |
173 | |