]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Host/posix/DomainSocket.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / Host / posix / DomainSocket.cpp
1 //===-- DomainSocket.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Host/posix/DomainSocket.h"
11
12 #include "lldb/Host/FileSystem.h"
13
14 #include <stddef.h>
15 #include <sys/socket.h>
16 #include <sys/un.h>
17
18 using namespace lldb;
19 using namespace lldb_private;
20
21 #ifdef __ANDROID__
22 // Android does not have SUN_LEN
23 #ifndef SUN_LEN
24 #define SUN_LEN(ptr) (offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path))
25 #endif
26 #endif // #ifdef __ANDROID__
27
28 namespace {
29
30 const int kDomain = AF_UNIX;
31 const int kType   = SOCK_STREAM;
32
33 bool SetSockAddr(llvm::StringRef name,
34                  const size_t name_offset,
35                  sockaddr_un* saddr_un,
36                  socklen_t& saddr_un_len)
37 {
38     if (name.size() + name_offset > sizeof(saddr_un->sun_path))
39         return false;
40
41     memset(saddr_un, 0, sizeof(*saddr_un));
42     saddr_un->sun_family = kDomain;
43
44     memcpy(saddr_un->sun_path + name_offset, name.data(), name.size());
45
46     // For domain sockets we can use SUN_LEN in order to calculate size of
47     // sockaddr_un, but for abstract sockets we have to calculate size manually
48     // because of leading null symbol.
49     if (name_offset == 0)
50         saddr_un_len = SUN_LEN(saddr_un);
51     else
52         saddr_un_len = offsetof(struct sockaddr_un, sun_path) + name_offset + name.size();
53
54 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
55     saddr_un->sun_len = saddr_un_len;
56 #endif
57
58     return true;
59 }
60
61 }
62
63 DomainSocket::DomainSocket(NativeSocket socket)
64     : Socket(socket, ProtocolUnixDomain, true)
65 {
66 }
67
68 DomainSocket::DomainSocket(bool child_processes_inherit, Error &error)
69     : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error))
70 {
71 }
72
73 DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error)
74     : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true)
75 {
76 }
77
78 Error
79 DomainSocket::Connect(llvm::StringRef name)
80 {
81     sockaddr_un saddr_un;
82     socklen_t saddr_un_len;
83     if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
84         return Error("Failed to set socket address");
85
86     Error error;
87     if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < 0)
88         SetLastError (error);
89
90     return error;
91 }
92
93 Error
94 DomainSocket::Listen(llvm::StringRef name, int backlog)
95 {
96     sockaddr_un saddr_un;
97     socklen_t saddr_un_len;
98     if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
99         return Error("Failed to set socket address");
100
101     DeleteSocketFile(name);
102
103     Error error;
104     if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == 0)
105         if (::listen(GetNativeSocket(), backlog) == 0)
106             return error;
107
108     SetLastError(error);
109     return error;
110 }
111
112 Error
113 DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
114 {
115     Error error;
116     auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error);
117     if (error.Success())
118         socket = new DomainSocket(conn_fd);
119
120     return error;
121 }
122
123 size_t
124 DomainSocket::GetNameOffset() const
125 {
126     return 0;
127 }
128
129 void
130 DomainSocket::DeleteSocketFile(llvm::StringRef name)
131 {
132     FileSystem::Unlink(FileSpec{name, true});
133 }