| //===----------------- SocketTestUtilities.cpp ------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "SocketTestUtilities.h" |
| #include "lldb/Host/Config.h" |
| #include "lldb/Utility/StreamString.h" |
| |
| #ifdef _WIN32 |
| #include <winsock2.h> |
| #include <ws2tcpip.h> |
| #else |
| #include <arpa/inet.h> |
| #endif |
| |
| using namespace lldb_private; |
| |
| static void AcceptThread(Socket *listen_socket, bool child_processes_inherit, |
| Socket **accept_socket, Status *error) { |
| *error = listen_socket->Accept(*accept_socket); |
| } |
| |
| template <typename SocketType> |
| void lldb_private::CreateConnectedSockets( |
| llvm::StringRef listen_remote_address, |
| const std::function<std::string(const SocketType &)> &get_connect_addr, |
| std::unique_ptr<SocketType> *a_up, std::unique_ptr<SocketType> *b_up) { |
| bool child_processes_inherit = false; |
| Status error; |
| std::unique_ptr<SocketType> listen_socket_up( |
| new SocketType(true, child_processes_inherit)); |
| EXPECT_FALSE(error.Fail()); |
| error = listen_socket_up->Listen(listen_remote_address, 5); |
| EXPECT_FALSE(error.Fail()); |
| EXPECT_TRUE(listen_socket_up->IsValid()); |
| |
| Status accept_error; |
| Socket *accept_socket; |
| std::thread accept_thread(AcceptThread, listen_socket_up.get(), |
| child_processes_inherit, &accept_socket, |
| &accept_error); |
| |
| std::string connect_remote_address = get_connect_addr(*listen_socket_up); |
| std::unique_ptr<SocketType> connect_socket_up( |
| new SocketType(true, child_processes_inherit)); |
| EXPECT_FALSE(error.Fail()); |
| error = connect_socket_up->Connect(connect_remote_address); |
| EXPECT_FALSE(error.Fail()); |
| EXPECT_TRUE(connect_socket_up->IsValid()); |
| |
| a_up->swap(connect_socket_up); |
| EXPECT_TRUE(error.Success()); |
| EXPECT_NE(nullptr, a_up->get()); |
| EXPECT_TRUE((*a_up)->IsValid()); |
| |
| accept_thread.join(); |
| b_up->reset(static_cast<SocketType *>(accept_socket)); |
| EXPECT_TRUE(accept_error.Success()); |
| EXPECT_NE(nullptr, b_up->get()); |
| EXPECT_TRUE((*b_up)->IsValid()); |
| |
| listen_socket_up.reset(); |
| } |
| |
| bool lldb_private::CreateTCPConnectedSockets( |
| std::string listen_remote_ip, std::unique_ptr<TCPSocket> *socket_a_up, |
| std::unique_ptr<TCPSocket> *socket_b_up) { |
| StreamString strm; |
| strm.Printf("[%s]:0", listen_remote_ip.c_str()); |
| CreateConnectedSockets<TCPSocket>( |
| strm.GetString(), |
| [=](const TCPSocket &s) { |
| char connect_remote_address[64]; |
| snprintf(connect_remote_address, sizeof(connect_remote_address), |
| "[%s]:%u", listen_remote_ip.c_str(), s.GetLocalPortNumber()); |
| return std::string(connect_remote_address); |
| }, |
| socket_a_up, socket_b_up); |
| return true; |
| } |
| |
| #if LLDB_ENABLE_POSIX |
| void lldb_private::CreateDomainConnectedSockets( |
| llvm::StringRef path, std::unique_ptr<DomainSocket> *socket_a_up, |
| std::unique_ptr<DomainSocket> *socket_b_up) { |
| return CreateConnectedSockets<DomainSocket>( |
| path, [=](const DomainSocket &) { return path.str(); }, socket_a_up, |
| socket_b_up); |
| } |
| #endif |
| |
| bool lldb_private::IsAddressFamilySupported(std::string ip) { |
| auto addresses = lldb_private::SocketAddress::GetAddressInfo( |
| ip.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); |
| return addresses.size() > 0; |
| } |
| |
| bool lldb_private::IsIPv4(std::string ip) { |
| struct sockaddr_in sock_addr; |
| return inet_pton(AF_INET, ip.c_str(), &(sock_addr.sin_addr)) != 0; |
| } |