1 //===-- SocketTestUtilities.cpp -------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "SocketTestUtilities.h" 10 #include "lldb/Host/Config.h" 11 #include "lldb/Utility/StreamString.h" 12 13 #ifdef _WIN32 14 #include <winsock2.h> 15 #include <ws2tcpip.h> 16 #else 17 #include <arpa/inet.h> 18 #endif 19 20 using namespace lldb_private; 21 22 static void AcceptThread(Socket *listen_socket, bool child_processes_inherit, 23 Socket **accept_socket, Status *error) { 24 *error = listen_socket->Accept(*accept_socket); 25 } 26 27 template <typename SocketType> 28 void lldb_private::CreateConnectedSockets( 29 llvm::StringRef listen_remote_address, 30 const std::function<std::string(const SocketType &)> &get_connect_addr, 31 std::unique_ptr<SocketType> *a_up, std::unique_ptr<SocketType> *b_up) { 32 bool child_processes_inherit = false; 33 Status error; 34 std::unique_ptr<SocketType> listen_socket_up( 35 new SocketType(true, child_processes_inherit)); 36 EXPECT_FALSE(error.Fail()); 37 error = listen_socket_up->Listen(listen_remote_address, 5); 38 EXPECT_FALSE(error.Fail()); 39 EXPECT_TRUE(listen_socket_up->IsValid()); 40 41 Status accept_error; 42 Socket *accept_socket; 43 std::thread accept_thread(AcceptThread, listen_socket_up.get(), 44 child_processes_inherit, &accept_socket, 45 &accept_error); 46 47 std::string connect_remote_address = get_connect_addr(*listen_socket_up); 48 std::unique_ptr<SocketType> connect_socket_up( 49 new SocketType(true, child_processes_inherit)); 50 EXPECT_FALSE(error.Fail()); 51 error = connect_socket_up->Connect(connect_remote_address); 52 EXPECT_FALSE(error.Fail()); 53 EXPECT_TRUE(connect_socket_up->IsValid()); 54 55 a_up->swap(connect_socket_up); 56 EXPECT_TRUE(error.Success()); 57 EXPECT_NE(nullptr, a_up->get()); 58 EXPECT_TRUE((*a_up)->IsValid()); 59 60 accept_thread.join(); 61 b_up->reset(static_cast<SocketType *>(accept_socket)); 62 EXPECT_TRUE(accept_error.Success()); 63 EXPECT_NE(nullptr, b_up->get()); 64 EXPECT_TRUE((*b_up)->IsValid()); 65 66 listen_socket_up.reset(); 67 } 68 69 bool lldb_private::CreateTCPConnectedSockets( 70 std::string listen_remote_ip, std::unique_ptr<TCPSocket> *socket_a_up, 71 std::unique_ptr<TCPSocket> *socket_b_up) { 72 StreamString strm; 73 strm.Printf("[%s]:0", listen_remote_ip.c_str()); 74 CreateConnectedSockets<TCPSocket>( 75 strm.GetString(), 76 [=](const TCPSocket &s) { 77 char connect_remote_address[64]; 78 snprintf(connect_remote_address, sizeof(connect_remote_address), 79 "[%s]:%u", listen_remote_ip.c_str(), s.GetLocalPortNumber()); 80 return std::string(connect_remote_address); 81 }, 82 socket_a_up, socket_b_up); 83 return true; 84 } 85 86 #if LLDB_ENABLE_POSIX 87 void lldb_private::CreateDomainConnectedSockets( 88 llvm::StringRef path, std::unique_ptr<DomainSocket> *socket_a_up, 89 std::unique_ptr<DomainSocket> *socket_b_up) { 90 return CreateConnectedSockets<DomainSocket>( 91 path, [=](const DomainSocket &) { return path.str(); }, socket_a_up, 92 socket_b_up); 93 } 94 #endif 95 96 bool lldb_private::IsAddressFamilySupported(std::string ip) { 97 auto addresses = lldb_private::SocketAddress::GetAddressInfo( 98 ip.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); 99 return addresses.size() > 0; 100 } 101 102 bool lldb_private::IsIPv4(std::string ip) { 103 struct sockaddr_in sock_addr; 104 return inet_pton(AF_INET, ip.c_str(), &(sock_addr.sin_addr)) != 0; 105 } 106