1 //===-- RNBSocketTest.cpp ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "gtest/gtest.h" 11 12 #include <arpa/inet.h> 13 #include <sys/sysctl.h> 14 #include <unistd.h> 15 16 #include "RNBDefs.h" 17 #include "RNBSocket.h" 18 #include "lldb/Host/Socket.h" 19 #include "lldb/Host/StringConvert.h" 20 #include "lldb/Host/common/TCPSocket.h" 21 22 using namespace lldb_private; 23 24 std::string hello = "Hello, world!"; 25 std::string goodbye = "Goodbye!"; 26 27 static void ServerCallbackv4(const void *baton, in_port_t port) { 28 auto child_pid = fork(); 29 if (child_pid == 0) { 30 Socket *client_socket; 31 char addr_buffer[256]; 32 sprintf(addr_buffer, "%s:%d", baton, port); 33 Error err = Socket::TcpConnect(addr_buffer, false, client_socket); 34 if (err.Fail()) 35 abort(); 36 char buffer[32]; 37 size_t read_size = 32; 38 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(addr, NULL); 58 if (addresses.size() == 0) 59 return; 60 61 char addr_wrap[256]; 62 if (addresses.front().GetFamily() == AF_INET6) 63 sprintf(addr_wrap, "[%s]", addr); 64 else 65 sprintf(addr_wrap, "%s", addr); 66 67 RNBSocket server_socket; 68 auto result = 69 server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr_wrap); 70 ASSERT_TRUE(result == rnb_success); 71 result = server_socket.Write(hello.c_str(), hello.length()); 72 ASSERT_TRUE(result == rnb_success); 73 std::string bye; 74 result = server_socket.Read(bye); 75 ASSERT_TRUE(result == rnb_success); 76 ASSERT_EQ(bye, goodbye); 77 78 int exit_status; 79 wait(&exit_status); 80 ASSERT_EQ(exit_status, 0); 81 } 82 83 TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); } 84 85 TEST(RNBSocket, LoopBackListenIPv6) { TestSocketListen("::1"); } 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(addr, NULL); 90 if (addresses.size() == 0) 91 return; 92 93 char addr_wrap[256]; 94 if (addresses.front().GetFamily() == AF_INET6) 95 sprintf(addr_wrap, "[%s]:0", addr); 96 else 97 sprintf(addr_wrap, "%s:0", addr); 98 99 Socket *server_socket; 100 Predicate<uint16_t> port_predicate; 101 port_predicate.SetValue(0, eBroadcastNever); 102 Error err = 103 Socket::TcpListen(addr_wrap, false, server_socket, &port_predicate); 104 ASSERT_FALSE(err.Fail()); 105 106 auto port = ((TCPSocket *)server_socket)->GetLocalPortNumber(); 107 auto child_pid = fork(); 108 if (child_pid != 0) { 109 RNBSocket client_socket; 110 auto result = client_socket.Connect(addr, port); 111 ASSERT_TRUE(result == rnb_success); 112 result = client_socket.Write(hello.c_str(), hello.length()); 113 ASSERT_TRUE(result == rnb_success); 114 std::string bye; 115 result = client_socket.Read(bye); 116 ASSERT_TRUE(result == rnb_success); 117 ASSERT_EQ(bye, goodbye); 118 } else { 119 Socket *connected_socket; 120 err = server_socket->Accept(connected_socket); 121 if (err.Fail()) { 122 llvm::errs() << err.AsCString(); 123 abort(); 124 } 125 char buffer[32]; 126 size_t read_size = 32; 127 err = connected_socket->Read((void *)&buffer[0], read_size); 128 if (err.Fail()) { 129 llvm::errs() << err.AsCString(); 130 abort(); 131 } 132 std::string Recv(&buffer[0], read_size); 133 if (Recv != hello) { 134 llvm::errs() << err.AsCString(); 135 abort(); 136 } 137 size_t write_size = goodbye.length(); 138 err = connected_socket->Write(goodbye.c_str(), write_size); 139 if (err.Fail()) { 140 llvm::errs() << err.AsCString(); 141 abort(); 142 } 143 if (write_size != goodbye.length()) { 144 llvm::errs() << err.AsCString(); 145 abort(); 146 } 147 exit(0); 148 } 149 int exit_status; 150 wait(&exit_status); 151 ASSERT_EQ(exit_status, 0); 152 } 153 154 TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); } 155 156 TEST(RNBSocket, LoopBackConnectIPv6) { TestSocketConnect("::1"); } 157