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 <sys/socket.h> 15 #include <sys/un.h> 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 #ifdef __ANDROID__ 21 // Android does not have SUN_LEN 22 #ifndef SUN_LEN 23 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path)) 24 #endif 25 #endif // #ifdef __ANDROID__ 26 27 namespace { 28 29 const int kDomain = AF_UNIX; 30 const int kType = SOCK_STREAM; 31 32 bool SetSockAddr(llvm::StringRef name, const size_t name_offset, sockaddr_un* saddr_un) 33 { 34 if (name.size() + name_offset > sizeof(saddr_un->sun_path)) 35 return false; 36 37 saddr_un->sun_family = kDomain; 38 memset(saddr_un->sun_path, 0, sizeof(saddr_un->sun_path)); 39 40 strncpy(&saddr_un->sun_path[name_offset], name.data(), name.size()); 41 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) 42 saddr_un->sun_len = SUN_LEN (saddr_un); 43 #endif 44 return true; 45 } 46 47 } 48 49 DomainSocket::DomainSocket(NativeSocket socket) 50 : Socket(socket, ProtocolUnixDomain, true) 51 { 52 } 53 54 DomainSocket::DomainSocket(bool child_processes_inherit, Error &error) 55 : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) 56 { 57 } 58 59 DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error) 60 : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true) 61 { 62 } 63 64 Error 65 DomainSocket::Connect(llvm::StringRef name) 66 { 67 sockaddr_un saddr_un; 68 if (!SetSockAddr(name, GetNameOffset(), &saddr_un)) 69 return Error("Failed to set socket address"); 70 71 Error error; 72 if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) < 0) 73 SetLastError (error); 74 75 return error; 76 } 77 78 Error 79 DomainSocket::Listen(llvm::StringRef name, int backlog) 80 { 81 sockaddr_un saddr_un; 82 if (!SetSockAddr(name, GetNameOffset(), &saddr_un)) 83 return Error("Failed to set socket address"); 84 85 DeleteSocketFile(name); 86 87 Error error; 88 if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) == 0) 89 if (::listen(GetNativeSocket(), backlog) == 0) 90 return error; 91 92 SetLastError(error); 93 return error; 94 } 95 96 Error 97 DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) 98 { 99 Error error; 100 auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error); 101 if (error.Success()) 102 socket = new DomainSocket(conn_fd); 103 104 return error; 105 } 106 107 size_t 108 DomainSocket::GetNameOffset() const 109 { 110 return 0; 111 } 112 113 void 114 DomainSocket::DeleteSocketFile(llvm::StringRef name) 115 { 116 FileSystem::Unlink(FileSpec{name, true}); 117 } 118