1 //===-- RNBSocketTest.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 "gtest/gtest.h" 10 11 #include <arpa/inet.h> 12 #include <sys/sysctl.h> 13 #include <unistd.h> 14 15 #include "RNBDefs.h" 16 #include "RNBSocket.h" 17 #include "lldb/Host/Socket.h" 18 #include "lldb/Host/common/TCPSocket.h" 19 #include "llvm/Testing/Support/Error.h" 20 21 using namespace lldb_private; 22 23 std::string hello = "Hello, world!"; 24 std::string goodbye = "Goodbye!"; 25 26 static void ServerCallbackv4(const void *baton, in_port_t port) { 27 auto child_pid = fork(); 28 if (child_pid == 0) { 29 std::string addr_buffer = 30 llvm::formatv("{0}:{1}", (const char *)baton, port).str(); 31 llvm::Expected<std::unique_ptr<Socket>> socket_or_err = 32 Socket::TcpConnect(addr_buffer); 33 ASSERT_THAT_EXPECTED(socket_or_err, llvm::Succeeded()); 34 Socket *client_socket = socket_or_err->get(); 35 36 char buffer[32]; 37 size_t read_size = 32; 38 Status err = client_socket->Read((void *)&buffer[0], read_size); 39 if (err.Fail()) 40 abort(); 41 std::string Recv(&buffer[0], read_size); 42 if (Recv != hello) 43 abort(); 44 size_t write_size = goodbye.length(); 45 err = client_socket->Write(goodbye.c_str(), write_size); 46 if (err.Fail()) 47 abort(); 48 if (write_size != goodbye.length()) 49 abort(); 50 delete client_socket; 51 exit(0); 52 } 53 } 54 55 void TestSocketListen(const char *addr) { 56 // Skip IPv6 tests if there isn't a valid interafce 57 auto addresses = lldb_private::SocketAddress::GetAddressInfo( 58 addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); 59 if (addresses.size() == 0) 60 return; 61 62 const char *fmt = addresses.front().GetFamily() == AF_INET6 ? "[{0}]" : "{0}"; 63 std::string addr_wrap = llvm::formatv(fmt, addr).str(); 64 65 RNBSocket server_socket; 66 auto result = server_socket.Listen(addr, 0, ServerCallbackv4, 67 (const void *)addr_wrap.c_str()); 68 ASSERT_TRUE(result == rnb_success); 69 result = server_socket.Write(hello.c_str(), hello.length()); 70 ASSERT_TRUE(result == rnb_success); 71 std::string bye; 72 result = server_socket.Read(bye); 73 ASSERT_TRUE(result == rnb_success); 74 ASSERT_EQ(bye, goodbye); 75 76 int exit_status; 77 wait(&exit_status); 78 ASSERT_EQ(exit_status, 0); 79 } 80 81 TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); } 82 83 TEST(RNBSocket, LoopBackListenIPv6) { TestSocketListen("::1"); } 84 85 TEST(RNBSocket, AnyListen) { TestSocketListen("*"); } 86 87 void TestSocketConnect(const char *addr) { 88 // Skip IPv6 tests if there isn't a valid interafce 89 auto addresses = lldb_private::SocketAddress::GetAddressInfo( 90 addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); 91 if (addresses.size() == 0) 92 return; 93 94 const char *fmt = 95 addresses.front().GetFamily() == AF_INET6 ? "[{0}]:0" : "{0}:0"; 96 std::string addr_wrap = llvm::formatv(fmt, addr).str(); 97 98 Socket *server_socket; 99 llvm::Expected<std::unique_ptr<Socket>> socket_or_err = 100 Socket::TcpListen(addr_wrap, false); 101 ASSERT_THAT_EXPECTED(socket_or_err, llvm::Succeeded()); 102 server_socket = socket_or_err->get(); 103 104 auto port = ((TCPSocket *)server_socket)->GetLocalPortNumber(); 105 auto child_pid = fork(); 106 if (child_pid != 0) { 107 RNBSocket client_socket; 108 auto result = client_socket.Connect(addr, port); 109 ASSERT_TRUE(result == rnb_success); 110 result = client_socket.Write(hello.c_str(), hello.length()); 111 ASSERT_TRUE(result == rnb_success); 112 std::string bye; 113 result = client_socket.Read(bye); 114 ASSERT_TRUE(result == rnb_success); 115 ASSERT_EQ(bye, goodbye); 116 } else { 117 Socket *connected_socket; 118 Status err = 119 server_socket->Accept(std::chrono::seconds(10), connected_socket); 120 if (err.Fail()) { 121 llvm::errs() << err.AsCString(); 122 abort(); 123 } 124 char buffer[32]; 125 size_t read_size = 32; 126 err = connected_socket->Read((void *)&buffer[0], read_size); 127 if (err.Fail()) { 128 llvm::errs() << err.AsCString(); 129 abort(); 130 } 131 std::string Recv(&buffer[0], read_size); 132 if (Recv != hello) { 133 llvm::errs() << err.AsCString(); 134 abort(); 135 } 136 size_t write_size = goodbye.length(); 137 err = connected_socket->Write(goodbye.c_str(), write_size); 138 if (err.Fail()) { 139 llvm::errs() << err.AsCString(); 140 abort(); 141 } 142 if (write_size != goodbye.length()) { 143 llvm::errs() << err.AsCString(); 144 abort(); 145 } 146 exit(0); 147 } 148 int exit_status; 149 wait(&exit_status); 150 ASSERT_EQ(exit_status, 0); 151 } 152 153 TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); } 154 155 TEST(RNBSocket, LoopBackConnectIPv6) { TestSocketConnect("::1"); } 156