Path: blob/main/contrib/llvm-project/lldb/source/Host/posix/DomainSocket.cpp
39607 views
//===-- DomainSocket.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Host/posix/DomainSocket.h"910#include "llvm/Support/Errno.h"11#include "llvm/Support/FileSystem.h"1213#include <cstddef>14#include <sys/socket.h>15#include <sys/un.h>1617using namespace lldb;18using namespace lldb_private;1920#ifdef __ANDROID__21// Android does not have SUN_LEN22#ifndef SUN_LEN23#define SUN_LEN(ptr) \24(offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path))25#endif26#endif // #ifdef __ANDROID__2728static const int kDomain = AF_UNIX;29static const int kType = SOCK_STREAM;3031static bool SetSockAddr(llvm::StringRef name, const size_t name_offset,32sockaddr_un *saddr_un, socklen_t &saddr_un_len) {33if (name.size() + name_offset > sizeof(saddr_un->sun_path))34return false;3536memset(saddr_un, 0, sizeof(*saddr_un));37saddr_un->sun_family = kDomain;3839memcpy(saddr_un->sun_path + name_offset, name.data(), name.size());4041// For domain sockets we can use SUN_LEN in order to calculate size of42// sockaddr_un, but for abstract sockets we have to calculate size manually43// because of leading null symbol.44if (name_offset == 0)45saddr_un_len = SUN_LEN(saddr_un);46else47saddr_un_len =48offsetof(struct sockaddr_un, sun_path) + name_offset + name.size();4950#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \51defined(__OpenBSD__)52saddr_un->sun_len = saddr_un_len;53#endif5455return true;56}5758DomainSocket::DomainSocket(bool should_close, bool child_processes_inherit)59: Socket(ProtocolUnixDomain, should_close, child_processes_inherit) {}6061DomainSocket::DomainSocket(SocketProtocol protocol,62bool child_processes_inherit)63: Socket(protocol, true, child_processes_inherit) {}6465DomainSocket::DomainSocket(NativeSocket socket,66const DomainSocket &listen_socket)67: Socket(ProtocolUnixDomain, listen_socket.m_should_close_fd,68listen_socket.m_child_processes_inherit) {69m_socket = socket;70}7172Status DomainSocket::Connect(llvm::StringRef name) {73sockaddr_un saddr_un;74socklen_t saddr_un_len;75if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))76return Status("Failed to set socket address");7778Status error;79m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);80if (error.Fail())81return error;82if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),83(struct sockaddr *)&saddr_un, saddr_un_len) < 0)84SetLastError(error);8586return error;87}8889Status DomainSocket::Listen(llvm::StringRef name, int backlog) {90sockaddr_un saddr_un;91socklen_t saddr_un_len;92if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))93return Status("Failed to set socket address");9495DeleteSocketFile(name);9697Status error;98m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);99if (error.Fail())100return error;101if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) ==1020)103if (::listen(GetNativeSocket(), backlog) == 0)104return error;105106SetLastError(error);107return error;108}109110Status DomainSocket::Accept(Socket *&socket) {111Status error;112auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr,113m_child_processes_inherit, error);114if (error.Success())115socket = new DomainSocket(conn_fd, *this);116117return error;118}119120size_t DomainSocket::GetNameOffset() const { return 0; }121122void DomainSocket::DeleteSocketFile(llvm::StringRef name) {123llvm::sys::fs::remove(name);124}125126std::string DomainSocket::GetSocketName() const {127if (m_socket == kInvalidSocketValue)128return "";129130struct sockaddr_un saddr_un;131saddr_un.sun_family = AF_UNIX;132socklen_t sock_addr_len = sizeof(struct sockaddr_un);133if (::getpeername(m_socket, (struct sockaddr *)&saddr_un, &sock_addr_len) !=1340)135return "";136137if (sock_addr_len <= offsetof(struct sockaddr_un, sun_path))138return ""; // Unnamed domain socket139140llvm::StringRef name(saddr_un.sun_path + GetNameOffset(),141sock_addr_len - offsetof(struct sockaddr_un, sun_path) -142GetNameOffset());143name = name.rtrim('\0');144145return name.str();146}147148std::string DomainSocket::GetRemoteConnectionURI() const {149std::string name = GetSocketName();150if (name.empty())151return name;152153return llvm::formatv(154"{0}://{1}",155GetNameOffset() == 0 ? "unix-connect" : "unix-abstract-connect", name);156}157158159