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