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