1 //===-- TcpSocket.cpp -------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Host/common/TCPSocket.h"
12 #include "lldb/Core/Log.h"
13 #include "lldb/Host/Config.h"
15 #ifndef LLDB_DISABLE_POSIX
16 #include <arpa/inet.h>
17 #include <netinet/tcp.h>
18 #include <sys/socket.h>
22 using namespace lldb_private;
26 const int kDomain = AF_INET;
27 const int kType = SOCK_STREAM;
31 TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
32 : Socket(socket, ProtocolTcp, should_close)
37 TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
38 : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, child_processes_inherit, error), true)
43 // Return the port number that is being used by the socket.
45 TCPSocket::GetLocalPortNumber() const
47 if (m_socket != kInvalidSocketValue)
49 SocketAddress sock_addr;
50 socklen_t sock_addr_len = sock_addr.GetMaxLength ();
51 if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
52 return sock_addr.GetPort ();
58 TCPSocket::GetLocalIPAddress() const
60 // We bound to port zero, so we need to figure out which port we actually bound to
61 if (m_socket != kInvalidSocketValue)
63 SocketAddress sock_addr;
64 socklen_t sock_addr_len = sock_addr.GetMaxLength ();
65 if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
66 return sock_addr.GetIPAddress ();
72 TCPSocket::GetRemotePortNumber() const
74 if (m_socket != kInvalidSocketValue)
76 SocketAddress sock_addr;
77 socklen_t sock_addr_len = sock_addr.GetMaxLength ();
78 if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
79 return sock_addr.GetPort ();
85 TCPSocket::GetRemoteIPAddress () const
87 // We bound to port zero, so we need to figure out which port we actually bound to
88 if (m_socket != kInvalidSocketValue)
90 SocketAddress sock_addr;
91 socklen_t sock_addr_len = sock_addr.GetMaxLength ();
92 if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
93 return sock_addr.GetIPAddress ();
99 TCPSocket::Connect(llvm::StringRef name)
101 if (m_socket == kInvalidSocketValue)
102 return Error("Invalid socket");
104 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
106 log->Printf ("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
109 std::string host_str;
110 std::string port_str;
111 int32_t port = INT32_MIN;
112 if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
115 // Enable local address reuse
116 SetOptionReuseAddress();
118 struct sockaddr_in sa;
119 ::memset (&sa, 0, sizeof (sa));
120 sa.sin_family = kDomain;
121 sa.sin_port = htons (port);
123 int inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
125 if (inet_pton_result <= 0)
127 struct hostent *host_entry = gethostbyname (host_str.c_str());
129 host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
130 inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
131 if (inet_pton_result <= 0)
133 if (inet_pton_result == -1)
136 error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
142 if (-1 == ::connect (GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa)))
144 SetLastError (error);
148 // Keep our TCP packets coming without any delays.
155 TCPSocket::Listen(llvm::StringRef name, int backlog)
159 // enable local address reuse
160 SetOptionReuseAddress();
162 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
164 log->Printf ("TCPSocket::%s (%s)", __FUNCTION__, name.data());
166 std::string host_str;
167 std::string port_str;
168 int32_t port = INT32_MIN;
169 if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
172 SocketAddress bind_addr;
174 // Only bind to the loopback address if we are expecting a connection from
175 // localhost to avoid any firewall issues.
176 const bool bind_addr_success = (host_str == "127.0.0.1") ?
177 bind_addr.SetToLocalhost (kDomain, port) :
178 bind_addr.SetToAnyAddress (kDomain, port);
180 if (!bind_addr_success)
182 error.SetErrorString("Failed to bind port");
186 int err = ::bind (GetNativeSocket(), bind_addr, bind_addr.GetLength());
188 err = ::listen (GetNativeSocket(), backlog);
191 SetLastError (error);
197 TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket)
200 std::string host_str;
201 std::string port_str;
203 if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
206 const sa_family_t family = kDomain;
207 const int socktype = kType;
208 const int protocol = IPPROTO_TCP;
209 SocketAddress listen_addr;
210 if (host_str.empty())
211 listen_addr.SetToLocalhost(family, port);
212 else if (host_str.compare("*") == 0)
213 listen_addr.SetToAnyAddress(family, port);
216 if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
218 error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
223 bool accept_connection = false;
224 std::unique_ptr<TCPSocket> accepted_socket;
226 // Loop until we are happy with our connection
227 while (!accept_connection)
229 struct sockaddr_in accept_addr;
230 ::memset (&accept_addr, 0, sizeof accept_addr);
231 #if !(defined (__linux__) || defined(_WIN32))
232 accept_addr.sin_len = sizeof accept_addr;
234 socklen_t accept_addr_len = sizeof accept_addr;
236 int sock = AcceptSocket (GetNativeSocket(),
237 (struct sockaddr *)&accept_addr,
239 child_processes_inherit,
245 bool is_same_addr = true;
246 #if !(defined(__linux__) || (defined(_WIN32)))
247 is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
250 is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr);
252 if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY))
254 accept_connection = true;
255 accepted_socket.reset(new TCPSocket(sock, true));
259 const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
260 const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
261 ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
262 accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
263 listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
264 accepted_socket.reset();
268 if (!accepted_socket)
271 // Keep our TCP packets coming without any delays.
272 accepted_socket->SetOptionNoDelay();
274 conn_socket = accepted_socket.release();
279 TCPSocket::SetOptionNoDelay()
281 return SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
285 TCPSocket::SetOptionReuseAddress()
287 return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);