1 //===-- llvm/Support/raw_socket_stream.cpp - Socket streams --*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains raw_ostream implementations for streams to communicate
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Support/raw_socket_stream.h"
15 #include "llvm/Config/config.h"
16 #include "llvm/Support/Error.h"
19 #include <sys/socket.h>
22 #include "llvm/Support/Windows/WindowsSupport.h"
23 // winsock2.h must be included before afunix.h. Briefly turn off clang-format to
32 #if defined(HAVE_UNISTD_H)
39 WSABalancer::WSABalancer() {
41 ::memset(&WsaData
, 0, sizeof(WsaData
));
42 if (WSAStartup(MAKEWORD(2, 2), &WsaData
) != 0) {
43 llvm::report_fatal_error("WSAStartup failed");
47 WSABalancer::~WSABalancer() { WSACleanup(); }
51 static std::error_code
getLastSocketErrorCode() {
53 return std::error_code(::WSAGetLastError(), std::system_category());
55 return std::error_code(errno
, std::system_category());
59 ListeningSocket::ListeningSocket(int SocketFD
, StringRef SocketPath
)
60 : FD(SocketFD
), SocketPath(SocketPath
) {}
62 ListeningSocket::ListeningSocket(ListeningSocket
&&LS
)
63 : FD(LS
.FD
), SocketPath(LS
.SocketPath
) {
67 Expected
<ListeningSocket
> ListeningSocket::createUnix(StringRef SocketPath
,
72 SOCKET MaybeWinsocket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
73 if (MaybeWinsocket
== INVALID_SOCKET
) {
75 int MaybeWinsocket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
76 if (MaybeWinsocket
== -1) {
78 return llvm::make_error
<StringError
>(getLastSocketErrorCode(),
79 "socket create failed");
82 struct sockaddr_un Addr
;
83 memset(&Addr
, 0, sizeof(Addr
));
84 Addr
.sun_family
= AF_UNIX
;
85 strncpy(Addr
.sun_path
, SocketPath
.str().c_str(), sizeof(Addr
.sun_path
) - 1);
87 if (bind(MaybeWinsocket
, (struct sockaddr
*)&Addr
, sizeof(Addr
)) == -1) {
88 std::error_code Err
= getLastSocketErrorCode();
89 if (Err
== std::errc::address_in_use
)
90 ::close(MaybeWinsocket
);
91 return llvm::make_error
<StringError
>(Err
, "Bind error");
93 if (listen(MaybeWinsocket
, MaxBacklog
) == -1) {
94 return llvm::make_error
<StringError
>(getLastSocketErrorCode(),
99 UnixSocket
= _open_osfhandle(MaybeWinsocket
, 0);
101 UnixSocket
= MaybeWinsocket
;
103 return ListeningSocket
{UnixSocket
, SocketPath
};
106 Expected
<std::unique_ptr
<raw_socket_stream
>> ListeningSocket::accept() {
109 SOCKET WinServerSock
= _get_osfhandle(FD
);
110 SOCKET WinAcceptSock
= ::accept(WinServerSock
, NULL
, NULL
);
111 AcceptFD
= _open_osfhandle(WinAcceptSock
, 0);
113 AcceptFD
= ::accept(FD
, NULL
, NULL
);
116 return llvm::make_error
<StringError
>(getLastSocketErrorCode(),
118 return std::make_unique
<raw_socket_stream
>(AcceptFD
);
121 ListeningSocket::~ListeningSocket() {
125 unlink(SocketPath
.c_str());
128 static Expected
<int> GetSocketFD(StringRef SocketPath
) {
130 SOCKET MaybeWinsocket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
131 if (MaybeWinsocket
== INVALID_SOCKET
) {
133 int MaybeWinsocket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
134 if (MaybeWinsocket
== -1) {
136 return llvm::make_error
<StringError
>(getLastSocketErrorCode(),
137 "Create socket failed");
140 struct sockaddr_un Addr
;
141 memset(&Addr
, 0, sizeof(Addr
));
142 Addr
.sun_family
= AF_UNIX
;
143 strncpy(Addr
.sun_path
, SocketPath
.str().c_str(), sizeof(Addr
.sun_path
) - 1);
145 int status
= connect(MaybeWinsocket
, (struct sockaddr
*)&Addr
, sizeof(Addr
));
147 return llvm::make_error
<StringError
>(getLastSocketErrorCode(),
148 "Connect socket failed");
151 return _open_osfhandle(MaybeWinsocket
, 0);
153 return MaybeWinsocket
;
157 raw_socket_stream::raw_socket_stream(int SocketFD
)
158 : raw_fd_stream(SocketFD
, true) {}
160 Expected
<std::unique_ptr
<raw_socket_stream
>>
161 raw_socket_stream::createConnectedUnix(StringRef SocketPath
) {
165 Expected
<int> FD
= GetSocketFD(SocketPath
);
167 return FD
.takeError();
168 return std::make_unique
<raw_socket_stream
>(*FD
);
171 raw_socket_stream::~raw_socket_stream() {}
173 //===----------------------------------------------------------------------===//
174 // raw_string_ostream
175 //===----------------------------------------------------------------------===//
177 void raw_string_ostream::write_impl(const char *Ptr
, size_t Size
) {
178 OS
.append(Ptr
, Size
);