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   RNBSocket server_socket;
57   auto result =
58       server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr);
59   ASSERT_TRUE(result == rnb_success);
60   result = server_socket.Write(hello.c_str(), hello.length());
61   ASSERT_TRUE(result == rnb_success);
62   std::string bye;
63   result = server_socket.Read(bye);
64   ASSERT_TRUE(result == rnb_success);
65   ASSERT_EQ(bye, goodbye);
66 
67   int exit_status;
68   wait(&exit_status);
69   ASSERT_EQ(exit_status, 0);
70 }
71 
72 TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); }
73 
74 void TestSocketConnect(const char *addr) {
75   char addr_wrap[256];
76   sprintf(addr_wrap, "%s:0", addr);
77 
78   Socket *server_socket;
79   Predicate<uint16_t> port_predicate;
80   port_predicate.SetValue(0, eBroadcastNever);
81   Error err =
82       Socket::TcpListen(addr_wrap, false, server_socket, &port_predicate);
83   ASSERT_FALSE(err.Fail());
84 
85   auto port = ((TCPSocket *)server_socket)->GetLocalPortNumber();
86   auto child_pid = fork();
87   if (child_pid != 0) {
88     RNBSocket client_socket;
89     auto result = client_socket.Connect(addr, port);
90     ASSERT_TRUE(result == rnb_success);
91     result = client_socket.Write(hello.c_str(), hello.length());
92     ASSERT_TRUE(result == rnb_success);
93     std::string bye;
94     result = client_socket.Read(bye);
95     ASSERT_TRUE(result == rnb_success);
96     ASSERT_EQ(bye, goodbye);
97   } else {
98     Socket *connected_socket;
99     err = server_socket->Accept(addr_wrap, false, connected_socket);
100     if (err.Fail()) {
101       llvm::errs() << err.AsCString();
102       abort();
103     }
104     char buffer[32];
105     size_t read_size = 32;
106     err = connected_socket->Read((void *)&buffer[0], read_size);
107     if (err.Fail()) {
108       llvm::errs() << err.AsCString();
109       abort();
110     }
111     std::string Recv(&buffer[0], read_size);
112     if (Recv != hello) {
113       llvm::errs() << err.AsCString();
114       abort();
115     }
116     size_t write_size = goodbye.length();
117     err = connected_socket->Write(goodbye.c_str(), write_size);
118     if (err.Fail()) {
119       llvm::errs() << err.AsCString();
120       abort();
121     }
122     if (write_size != goodbye.length()) {
123       llvm::errs() << err.AsCString();
124       abort();
125     }
126     exit(0);
127   }
128   int exit_status;
129   wait(&exit_status);
130   ASSERT_EQ(exit_status, 0);
131 }
132 
133 TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); }
134