Path: blob/main/contrib/llvm-project/lldb/source/Host/common/UDPSocket.cpp
39606 views
//===-- UDPSocket.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/common/UDPSocket.h"910#include "lldb/Host/Config.h"11#include "lldb/Utility/LLDBLog.h"12#include "lldb/Utility/Log.h"1314#if LLDB_ENABLE_POSIX15#include <arpa/inet.h>16#include <sys/socket.h>17#endif1819#include <memory>2021using namespace lldb;22using namespace lldb_private;2324static const int kDomain = AF_INET;25static const int kType = SOCK_DGRAM;2627static const char *g_not_supported_error = "Not supported";2829UDPSocket::UDPSocket(NativeSocket socket) : Socket(ProtocolUdp, true, true) {30m_socket = socket;31}3233UDPSocket::UDPSocket(bool should_close, bool child_processes_inherit)34: Socket(ProtocolUdp, should_close, child_processes_inherit) {}3536size_t UDPSocket::Send(const void *buf, const size_t num_bytes) {37return ::sendto(m_socket, static_cast<const char *>(buf), num_bytes, 0,38m_sockaddr, m_sockaddr.GetLength());39}4041Status UDPSocket::Connect(llvm::StringRef name) {42return Status("%s", g_not_supported_error);43}4445Status UDPSocket::Listen(llvm::StringRef name, int backlog) {46return Status("%s", g_not_supported_error);47}4849Status UDPSocket::Accept(Socket *&socket) {50return Status("%s", g_not_supported_error);51}5253llvm::Expected<std::unique_ptr<UDPSocket>>54UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit) {55std::unique_ptr<UDPSocket> socket;5657Log *log = GetLog(LLDBLog::Connection);58LLDB_LOG(log, "host/port = {0}", name);5960Status error;61llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);62if (!host_port)63return host_port.takeError();6465// At this point we have setup the receive port, now we need to setup the UDP66// send socket6768struct addrinfo hints;69struct addrinfo *service_info_list = nullptr;7071::memset(&hints, 0, sizeof(hints));72hints.ai_family = kDomain;73hints.ai_socktype = kType;74int err = ::getaddrinfo(host_port->hostname.c_str(), std::to_string(host_port->port).c_str(), &hints,75&service_info_list);76if (err != 0) {77error.SetErrorStringWithFormat(78#if defined(_WIN32) && defined(UNICODE)79"getaddrinfo(%s, %d, &hints, &info) returned error %i (%S)",80#else81"getaddrinfo(%s, %d, &hints, &info) returned error %i (%s)",82#endif83host_port->hostname.c_str(), host_port->port, err, gai_strerror(err));84return error.ToError();85}8687for (struct addrinfo *service_info_ptr = service_info_list;88service_info_ptr != nullptr;89service_info_ptr = service_info_ptr->ai_next) {90auto send_fd = CreateSocket(91service_info_ptr->ai_family, service_info_ptr->ai_socktype,92service_info_ptr->ai_protocol, child_processes_inherit, error);93if (error.Success()) {94socket.reset(new UDPSocket(send_fd));95socket->m_sockaddr = service_info_ptr;96break;97} else98continue;99}100101::freeaddrinfo(service_info_list);102103if (!socket)104return error.ToError();105106SocketAddress bind_addr;107108// Only bind to the loopback address if we are expecting a connection from109// localhost to avoid any firewall issues.110const bool bind_addr_success = (host_port->hostname == "127.0.0.1" || host_port->hostname == "localhost")111? bind_addr.SetToLocalhost(kDomain, host_port->port)112: bind_addr.SetToAnyAddress(kDomain, host_port->port);113114if (!bind_addr_success) {115error.SetErrorString("Failed to get hostspec to bind for");116return error.ToError();117}118119bind_addr.SetPort(0); // Let the source port # be determined dynamically120121err = ::bind(socket->GetNativeSocket(), bind_addr, bind_addr.GetLength());122123struct sockaddr_in source_info;124socklen_t address_len = sizeof (struct sockaddr_in);125err = ::getsockname(socket->GetNativeSocket(),126(struct sockaddr *)&source_info, &address_len);127128return std::move(socket);129}130131std::string UDPSocket::GetRemoteConnectionURI() const {132if (m_socket != kInvalidSocketValue) {133return std::string(llvm::formatv(134"udp://[{0}]:{1}", m_sockaddr.GetIPAddress(), m_sockaddr.GetPort()));135}136return "";137}138139140