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 //===----------------------------------------------------------------------===//
11 #define _WINSOCK_DEPRECATED_NO_WARNINGS
14 #include "lldb/Host/common/TCPSocket.h"
16 #include "lldb/Core/Log.h"
17 #include "lldb/Host/Config.h"
19 #ifndef LLDB_DISABLE_POSIX
20 #include <arpa/inet.h>
21 #include <netinet/tcp.h>
22 #include <sys/socket.h>
26 using namespace lldb_private;
30 const int kDomain = AF_INET;
31 const int kType = SOCK_STREAM;
34 TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
35 : Socket(socket, ProtocolTcp, should_close) {}
37 TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
38 : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP,
39 child_processes_inherit, error),
42 // Return the port number that is being used by the socket.
43 uint16_t TCPSocket::GetLocalPortNumber() const {
44 if (m_socket != kInvalidSocketValue) {
45 SocketAddress sock_addr;
46 socklen_t sock_addr_len = sock_addr.GetMaxLength();
47 if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
48 return sock_addr.GetPort();
53 std::string TCPSocket::GetLocalIPAddress() const {
54 // We bound to port zero, so we need to figure out which port we actually
56 if (m_socket != kInvalidSocketValue) {
57 SocketAddress sock_addr;
58 socklen_t sock_addr_len = sock_addr.GetMaxLength();
59 if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
60 return sock_addr.GetIPAddress();
65 uint16_t TCPSocket::GetRemotePortNumber() const {
66 if (m_socket != kInvalidSocketValue) {
67 SocketAddress sock_addr;
68 socklen_t sock_addr_len = sock_addr.GetMaxLength();
69 if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
70 return sock_addr.GetPort();
75 std::string TCPSocket::GetRemoteIPAddress() const {
76 // We bound to port zero, so we need to figure out which port we actually
78 if (m_socket != kInvalidSocketValue) {
79 SocketAddress sock_addr;
80 socklen_t sock_addr_len = sock_addr.GetMaxLength();
81 if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
82 return sock_addr.GetIPAddress();
87 Error TCPSocket::Connect(llvm::StringRef name) {
88 if (m_socket == kInvalidSocketValue)
89 return Error("Invalid socket");
91 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION));
93 log->Printf("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
98 int32_t port = INT32_MIN;
99 if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
102 struct sockaddr_in sa;
103 ::memset(&sa, 0, sizeof(sa));
104 sa.sin_family = kDomain;
105 sa.sin_port = htons(port);
107 int inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr);
109 if (inet_pton_result <= 0) {
110 struct hostent *host_entry = gethostbyname(host_str.c_str());
112 host_str = ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list);
113 inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr);
114 if (inet_pton_result <= 0) {
115 if (inet_pton_result == -1)
118 error.SetErrorStringWithFormat("invalid host string: '%s'",
126 ::connect(GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) {
131 // Keep our TCP packets coming without any delays.
137 Error TCPSocket::Listen(llvm::StringRef name, int backlog) {
140 // enable local address reuse
141 SetOptionReuseAddress();
143 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
145 log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data());
147 std::string host_str;
148 std::string port_str;
149 int32_t port = INT32_MIN;
150 if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
153 SocketAddress bind_addr;
155 // Only bind to the loopback address if we are expecting a connection from
156 // localhost to avoid any firewall issues.
157 const bool bind_addr_success = (host_str == "127.0.0.1")
158 ? bind_addr.SetToLocalhost(kDomain, port)
159 : bind_addr.SetToAnyAddress(kDomain, port);
161 if (!bind_addr_success) {
162 error.SetErrorString("Failed to bind port");
166 int err = ::bind(GetNativeSocket(), bind_addr, bind_addr.GetLength());
168 err = ::listen(GetNativeSocket(), backlog);
176 Error TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
177 Socket *&conn_socket) {
179 std::string host_str;
180 std::string port_str;
182 if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
185 const sa_family_t family = kDomain;
186 const int socktype = kType;
187 const int protocol = IPPROTO_TCP;
188 SocketAddress listen_addr;
189 if (host_str.empty())
190 listen_addr.SetToLocalhost(family, port);
191 else if (host_str.compare("*") == 0)
192 listen_addr.SetToAnyAddress(family, port);
194 if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family,
195 socktype, protocol)) {
196 error.SetErrorStringWithFormat("unable to resolve hostname '%s'",
202 bool accept_connection = false;
203 std::unique_ptr<TCPSocket> accepted_socket;
205 // Loop until we are happy with our connection
206 while (!accept_connection) {
207 struct sockaddr_in accept_addr;
208 ::memset(&accept_addr, 0, sizeof accept_addr);
209 #if !(defined(__linux__) || defined(_WIN32))
210 accept_addr.sin_len = sizeof accept_addr;
212 socklen_t accept_addr_len = sizeof accept_addr;
214 int sock = AcceptSocket(GetNativeSocket(), (struct sockaddr *)&accept_addr,
215 &accept_addr_len, child_processes_inherit, error);
220 bool is_same_addr = true;
221 #if !(defined(__linux__) || (defined(_WIN32)))
222 is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
225 is_same_addr = (accept_addr.sin_addr.s_addr ==
226 listen_addr.sockaddr_in().sin_addr.s_addr);
229 (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) {
230 accept_connection = true;
231 accepted_socket.reset(new TCPSocket(sock, true));
233 const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
234 const uint8_t *listen_ip =
235 (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
236 ::fprintf(stderr, "error: rejecting incoming connection from %u.%u.%u.%u "
237 "(expecting %u.%u.%u.%u)\n",
238 accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
239 listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
240 accepted_socket.reset();
244 if (!accepted_socket)
247 // Keep our TCP packets coming without any delays.
248 accepted_socket->SetOptionNoDelay();
250 conn_socket = accepted_socket.release();
254 int TCPSocket::SetOptionNoDelay() {
255 return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
258 int TCPSocket::SetOptionReuseAddress() {
259 return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);