1 //===-- SocketTest.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 <cstdio>
11 #include <functional>
12 #include <thread>
13 
14 #include "gtest/gtest.h"
15 
16 #include "lldb/Host/Config.h"
17 #include "lldb/Host/Socket.h"
18 #include "lldb/Host/common/TCPSocket.h"
19 #include "lldb/Host/common/UDPSocket.h"
20 
21 #ifndef LLDB_DISABLE_POSIX
22 #include "lldb/Host/posix/DomainSocket.h"
23 #endif
24 
25 using namespace lldb_private;
26 
27 class SocketTest : public testing::Test {
28 public:
29   void SetUp() override {
30 #if defined(_MSC_VER)
31     WSADATA data;
32     ::WSAStartup(MAKEWORD(2, 2), &data);
33 #endif
34   }
35 
36   void TearDown() override {
37 #if defined(_MSC_VER)
38     ::WSACleanup();
39 #endif
40   }
41 
42 protected:
43   static void AcceptThread(Socket *listen_socket,
44                            const char *listen_remote_address,
45                            bool child_processes_inherit, Socket **accept_socket,
46                            Error *error) {
47     *error = listen_socket->Accept(listen_remote_address,
48                                    child_processes_inherit, *accept_socket);
49   }
50 
51   template <typename SocketType>
52   void CreateConnectedSockets(
53       const char *listen_remote_address,
54       const std::function<std::string(const SocketType &)> &get_connect_addr,
55       std::unique_ptr<SocketType> *a_up, std::unique_ptr<SocketType> *b_up) {
56     bool child_processes_inherit = false;
57     Error error;
58     std::unique_ptr<SocketType> listen_socket_up(
59         new SocketType(child_processes_inherit, error));
60     EXPECT_FALSE(error.Fail());
61     error = listen_socket_up->Listen(listen_remote_address, 5);
62     EXPECT_FALSE(error.Fail());
63     EXPECT_TRUE(listen_socket_up->IsValid());
64 
65     Error accept_error;
66     Socket *accept_socket;
67     std::thread accept_thread(AcceptThread, listen_socket_up.get(),
68                               listen_remote_address, child_processes_inherit,
69                               &accept_socket, &accept_error);
70 
71     std::string connect_remote_address = get_connect_addr(*listen_socket_up);
72     std::unique_ptr<SocketType> connect_socket_up(
73         new SocketType(child_processes_inherit, error));
74     EXPECT_FALSE(error.Fail());
75     error = connect_socket_up->Connect(connect_remote_address);
76     EXPECT_FALSE(error.Fail());
77     EXPECT_TRUE(connect_socket_up->IsValid());
78 
79     a_up->swap(connect_socket_up);
80     EXPECT_TRUE(error.Success());
81     EXPECT_NE(nullptr, a_up->get());
82     EXPECT_TRUE((*a_up)->IsValid());
83 
84     accept_thread.join();
85     b_up->reset(static_cast<SocketType *>(accept_socket));
86     EXPECT_TRUE(accept_error.Success());
87     EXPECT_NE(nullptr, b_up->get());
88     EXPECT_TRUE((*b_up)->IsValid());
89 
90     listen_socket_up.reset();
91   }
92 };
93 
94 TEST_F(SocketTest, DecodeHostAndPort) {
95   std::string host_str;
96   std::string port_str;
97   int32_t port;
98   Error error;
99   EXPECT_TRUE(Socket::DecodeHostAndPort("localhost:1138", host_str, port_str,
100                                         port, &error));
101   EXPECT_STREQ("localhost", host_str.c_str());
102   EXPECT_STREQ("1138", port_str.c_str());
103   EXPECT_EQ(1138, port);
104   EXPECT_TRUE(error.Success());
105 
106   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:65536", host_str, port_str,
107                                          port, &error));
108   EXPECT_TRUE(error.Fail());
109   EXPECT_STREQ("invalid host:port specification: 'google.com:65536'",
110                error.AsCString());
111 
112   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:-1138", host_str, port_str,
113                                          port, &error));
114   EXPECT_TRUE(error.Fail());
115   EXPECT_STREQ("invalid host:port specification: 'google.com:-1138'",
116                error.AsCString());
117 
118   EXPECT_FALSE(Socket::DecodeHostAndPort("google.com:65536", host_str, port_str,
119                                          port, &error));
120   EXPECT_TRUE(error.Fail());
121   EXPECT_STREQ("invalid host:port specification: 'google.com:65536'",
122                error.AsCString());
123 
124   EXPECT_TRUE(
125       Socket::DecodeHostAndPort("12345", host_str, port_str, port, &error));
126   EXPECT_STREQ("", host_str.c_str());
127   EXPECT_STREQ("12345", port_str.c_str());
128   EXPECT_EQ(12345, port);
129   EXPECT_TRUE(error.Success());
130 
131   EXPECT_TRUE(
132       Socket::DecodeHostAndPort("*:0", host_str, port_str, port, &error));
133   EXPECT_STREQ("*", host_str.c_str());
134   EXPECT_STREQ("0", port_str.c_str());
135   EXPECT_EQ(0, port);
136   EXPECT_TRUE(error.Success());
137 
138   EXPECT_TRUE(
139       Socket::DecodeHostAndPort("*:65535", host_str, port_str, port, &error));
140   EXPECT_STREQ("*", host_str.c_str());
141   EXPECT_STREQ("65535", port_str.c_str());
142   EXPECT_EQ(65535, port);
143   EXPECT_TRUE(error.Success());
144 }
145 
146 #ifndef LLDB_DISABLE_POSIX
147 TEST_F(SocketTest, DomainListenConnectAccept) {
148   char *file_name_str = tempnam(nullptr, nullptr);
149   EXPECT_NE(nullptr, file_name_str);
150   const std::string file_name(file_name_str);
151   free(file_name_str);
152 
153   std::unique_ptr<DomainSocket> socket_a_up;
154   std::unique_ptr<DomainSocket> socket_b_up;
155   CreateConnectedSockets<DomainSocket>(
156       file_name.c_str(), [=](const DomainSocket &) { return file_name; },
157       &socket_a_up, &socket_b_up);
158 }
159 #endif
160 
161 TEST_F(SocketTest, TCPListen0ConnectAccept) {
162   std::unique_ptr<TCPSocket> socket_a_up;
163   std::unique_ptr<TCPSocket> socket_b_up;
164   CreateConnectedSockets<TCPSocket>(
165       "127.0.0.1:0",
166       [=](const TCPSocket &s) {
167         char connect_remote_address[64];
168         snprintf(connect_remote_address, sizeof(connect_remote_address),
169                  "localhost:%u", s.GetLocalPortNumber());
170         return std::string(connect_remote_address);
171       },
172       &socket_a_up, &socket_b_up);
173 }
174 
175 TEST_F(SocketTest, TCPGetAddress) {
176   std::unique_ptr<TCPSocket> socket_a_up;
177   std::unique_ptr<TCPSocket> socket_b_up;
178   CreateConnectedSockets<TCPSocket>(
179       "127.0.0.1:0",
180       [=](const TCPSocket &s) {
181         char connect_remote_address[64];
182         snprintf(connect_remote_address, sizeof(connect_remote_address),
183                  "localhost:%u", s.GetLocalPortNumber());
184         return std::string(connect_remote_address);
185       },
186       &socket_a_up, &socket_b_up);
187 
188   EXPECT_EQ(socket_a_up->GetLocalPortNumber(),
189             socket_b_up->GetRemotePortNumber());
190   EXPECT_EQ(socket_b_up->GetLocalPortNumber(),
191             socket_a_up->GetRemotePortNumber());
192   EXPECT_NE(socket_a_up->GetLocalPortNumber(),
193             socket_b_up->GetLocalPortNumber());
194   EXPECT_STREQ("127.0.0.1", socket_a_up->GetRemoteIPAddress().c_str());
195   EXPECT_STREQ("127.0.0.1", socket_b_up->GetRemoteIPAddress().c_str());
196 }
197 
198 TEST_F(SocketTest, UDPConnect) {
199   Socket *socket;
200 
201   bool child_processes_inherit = false;
202   auto error = UDPSocket::Connect("127.0.0.1:0", child_processes_inherit,
203                                   socket);
204 
205   std::unique_ptr<Socket> socket_up(socket);
206 
207   EXPECT_TRUE(error.Success());
208   EXPECT_TRUE(socket_up->IsValid());
209 }
210