TCPSocket.cpp revision 341825
178556Sobrien//===-- TCPSocket.cpp -------------------------------------------*- C++ -*-===// 278556Sobrien// 378556Sobrien// The LLVM Compiler Infrastructure 478556Sobrien// 578556Sobrien// This file is distributed under the University of Illinois Open Source 678556Sobrien// License. See LICENSE.TXT for details. 7167974Sdelphij// 8167974Sdelphij//===----------------------------------------------------------------------===// 9167974Sdelphij 1078556Sobrien#if defined(_MSC_VER) 11215041Sobrien#define _WINSOCK_DEPRECATED_NO_WARNINGS 12215041Sobrien#endif 1378556Sobrien 14167974Sdelphij#include "lldb/Host/common/TCPSocket.h" 15167974Sdelphij 1678556Sobrien#include "lldb/Host/Config.h" 17167974Sdelphij#include "lldb/Host/MainLoop.h" 18167974Sdelphij#include "lldb/Utility/Log.h" 19167974Sdelphij 2078556Sobrien#include "llvm/Config/llvm-config.h" 2178556Sobrien#include "llvm/Support/raw_ostream.h" 2278556Sobrien 2378556Sobrien#ifndef LLDB_DISABLE_POSIX 2478556Sobrien#include <arpa/inet.h> 2578556Sobrien#include <netinet/tcp.h> 2678556Sobrien#include <sys/socket.h> 2778556Sobrien#endif 2878556Sobrien 2978556Sobrien#if defined(_WIN32) 3078556Sobrien#include <winsock2.h> 3178556Sobrien#endif 3278556Sobrien 3378556Sobrien#ifdef _WIN32 3478556Sobrien#define CLOSE_SOCKET closesocket 3578556Sobrientypedef const char *set_socket_option_arg_type; 3678556Sobrien#else 3778556Sobrien#include <unistd.h> 3878556Sobrien#define CLOSE_SOCKET ::close 39215041Sobrientypedef const void *set_socket_option_arg_type; 4078556Sobrien#endif 4178556Sobrien 4278556Sobrienusing namespace lldb; 4378556Sobrienusing namespace lldb_private; 4478556Sobrien 4578556Sobriennamespace { 4678556Sobrienconst int kType = SOCK_STREAM; 4778556Sobrien} 4878556Sobrien 4978556SobrienTCPSocket::TCPSocket(bool should_close, bool child_processes_inherit) 5078556Sobrien : Socket(ProtocolTcp, should_close, child_processes_inherit) {} 5178556Sobrien 5278556SobrienTCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket) 5378556Sobrien : Socket(ProtocolTcp, listen_socket.m_should_close_fd, 5478556Sobrien listen_socket.m_child_processes_inherit) { 5578556Sobrien m_socket = socket; 5678556Sobrien} 57167974Sdelphij 5878556SobrienTCPSocket::TCPSocket(NativeSocket socket, bool should_close, 5978556Sobrien bool child_processes_inherit) 6078556Sobrien : Socket(ProtocolTcp, should_close, child_processes_inherit) { 61167974Sdelphij m_socket = socket; 6278556Sobrien} 6378556Sobrien 6478556SobrienTCPSocket::~TCPSocket() { CloseListenSockets(); } 6578556Sobrien 6678556Sobrienbool TCPSocket::IsValid() const { 6778556Sobrien return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0; 6878556Sobrien} 6978556Sobrien 7078556Sobrien// Return the port number that is being used by the socket. 7178556Sobrienuint16_t TCPSocket::GetLocalPortNumber() const { 72167974Sdelphij if (m_socket != kInvalidSocketValue) { 7378556Sobrien SocketAddress sock_addr; 7478556Sobrien socklen_t sock_addr_len = sock_addr.GetMaxLength(); 7578556Sobrien if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0) 7678556Sobrien return sock_addr.GetPort(); 7778556Sobrien } else if (!m_listen_sockets.empty()) { 7878556Sobrien SocketAddress sock_addr; 7978556Sobrien socklen_t sock_addr_len = sock_addr.GetMaxLength(); 8078556Sobrien if (::getsockname(m_listen_sockets.begin()->first, sock_addr, 8178556Sobrien &sock_addr_len) == 0) 8278556Sobrien return sock_addr.GetPort(); 8378556Sobrien } 8478556Sobrien return 0; 85167974Sdelphij} 8678556Sobrien 87167974Sdelphijstd::string TCPSocket::GetLocalIPAddress() const { 8878556Sobrien // We bound to port zero, so we need to figure out which port we actually 8978556Sobrien // bound to 9078556Sobrien if (m_socket != kInvalidSocketValue) { 91167974Sdelphij SocketAddress sock_addr; 92167974Sdelphij socklen_t sock_addr_len = sock_addr.GetMaxLength(); 93167974Sdelphij if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0) 94167974Sdelphij return sock_addr.GetIPAddress(); 95167974Sdelphij } 96167974Sdelphij return ""; 97167974Sdelphij} 98167974Sdelphij 9978556Sobrienuint16_t TCPSocket::GetRemotePortNumber() const { 10078556Sobrien if (m_socket != kInvalidSocketValue) { 10178556Sobrien SocketAddress sock_addr; 10278556Sobrien socklen_t sock_addr_len = sock_addr.GetMaxLength(); 10378556Sobrien if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0) 10478556Sobrien return sock_addr.GetPort(); 10578556Sobrien } 10690067Ssobomax return 0; 10790067Ssobomax} 10890067Ssobomax 10990067Ssobomaxstd::string TCPSocket::GetRemoteIPAddress() const { 11090067Ssobomax // We bound to port zero, so we need to figure out which port we actually 11190067Ssobomax // bound to 11290067Ssobomax if (m_socket != kInvalidSocketValue) { 11378556Sobrien SocketAddress sock_addr; 11478556Sobrien socklen_t sock_addr_len = sock_addr.GetMaxLength(); 11578556Sobrien if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0) 11678556Sobrien return sock_addr.GetIPAddress(); 11778556Sobrien } 11878556Sobrien return ""; 11978556Sobrien} 12078556Sobrien 12178556SobrienStatus TCPSocket::CreateSocket(int domain) { 12278556Sobrien Status error; 12378556Sobrien if (IsValid()) 12478556Sobrien error = Close(); 12578556Sobrien if (error.Fail()) 12678556Sobrien return error; 12778556Sobrien m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP, 12878556Sobrien m_child_processes_inherit, error); 12978556Sobrien return error; 13078556Sobrien} 13178556Sobrien 13278556SobrienStatus TCPSocket::Connect(llvm::StringRef name) { 13378556Sobrien 13478556Sobrien Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); 13578556Sobrien if (log) 13678556Sobrien log->Printf("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); 13778556Sobrien 13878556Sobrien Status error; 13978556Sobrien std::string host_str; 14078556Sobrien std::string port_str; 14178556Sobrien int32_t port = INT32_MIN; 14278556Sobrien if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) 14378556Sobrien return error; 14478556Sobrien 14578556Sobrien auto addresses = lldb_private::SocketAddress::GetAddressInfo( 14678556Sobrien host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); 14778556Sobrien for (auto address : addresses) { 14878556Sobrien error = CreateSocket(address.GetFamily()); 14978556Sobrien if (error.Fail()) 15078556Sobrien continue; 15178556Sobrien 15278556Sobrien address.SetPort(port); 15378556Sobrien 15478556Sobrien if (-1 == ::connect(GetNativeSocket(), &address.sockaddr(), 15578556Sobrien address.GetLength())) { 15678556Sobrien CLOSE_SOCKET(GetNativeSocket()); 15778556Sobrien continue; 15878556Sobrien } 15978556Sobrien 16078556Sobrien SetOptionNoDelay(); 16178556Sobrien 16278556Sobrien error.Clear(); 16378556Sobrien return error; 16478556Sobrien } 16578556Sobrien 16678556Sobrien error.SetErrorString("Failed to connect port"); 16778556Sobrien return error; 16878556Sobrien} 16978556Sobrien 17078556SobrienStatus TCPSocket::Listen(llvm::StringRef name, int backlog) { 17178556Sobrien Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 17278556Sobrien if (log) 17378556Sobrien log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data()); 17478556Sobrien 17578556Sobrien Status error; 17678556Sobrien std::string host_str; 17778556Sobrien std::string port_str; 17878556Sobrien int32_t port = INT32_MIN; 17978556Sobrien if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) 18078556Sobrien return error; 18178556Sobrien 18278556Sobrien if (host_str == "*") 18378556Sobrien host_str = "0.0.0.0"; 18478556Sobrien auto addresses = lldb_private::SocketAddress::GetAddressInfo( 18578556Sobrien host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); 18678556Sobrien for (auto address : addresses) { 18778556Sobrien int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP, 18878556Sobrien m_child_processes_inherit, error); 18978556Sobrien if (error.Fail()) { 19078556Sobrien error.Clear(); 19178556Sobrien continue; 19278556Sobrien } 19378556Sobrien 19478556Sobrien // enable local address reuse 19578556Sobrien int option_value = 1; 19678556Sobrien set_socket_option_arg_type option_value_p = 19778556Sobrien reinterpret_cast<set_socket_option_arg_type>(&option_value); 19878556Sobrien ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p, 19978556Sobrien sizeof(option_value)); 20078556Sobrien 20178556Sobrien SocketAddress listen_address = address; 20278556Sobrien if(!listen_address.IsLocalhost()) 20378556Sobrien listen_address.SetToAnyAddress(address.GetFamily(), port); 20478556Sobrien else 20578556Sobrien listen_address.SetPort(port); 20678556Sobrien 20778556Sobrien int err = 20878556Sobrien ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength()); 20978556Sobrien if (-1 != err) 21078556Sobrien err = ::listen(fd, backlog); 21178556Sobrien 21278556Sobrien if (-1 == err) { 21378556Sobrien CLOSE_SOCKET(fd); 21478556Sobrien continue; 21578556Sobrien } 21678556Sobrien 21778556Sobrien if (port == 0) { 21878556Sobrien socklen_t sa_len = address.GetLength(); 21978556Sobrien if (getsockname(fd, &address.sockaddr(), &sa_len) == 0) 22078556Sobrien port = address.GetPort(); 22178556Sobrien } 22278556Sobrien m_listen_sockets[fd] = address; 22378556Sobrien } 22478556Sobrien 22578556Sobrien if (m_listen_sockets.size() == 0) 22678556Sobrien error.SetErrorString("Failed to connect port"); 22778556Sobrien return error; 22878556Sobrien} 22978556Sobrien 23078556Sobrienvoid TCPSocket::CloseListenSockets() { 23178556Sobrien for (auto socket : m_listen_sockets) 23278556Sobrien CLOSE_SOCKET(socket.first); 23378556Sobrien m_listen_sockets.clear(); 23478556Sobrien} 23578556Sobrien 23678556SobrienStatus TCPSocket::Accept(Socket *&conn_socket) { 23778556Sobrien Status error; 23878556Sobrien if (m_listen_sockets.size() == 0) { 23978556Sobrien error.SetErrorString("No open listening sockets!"); 24078556Sobrien return error; 24178556Sobrien } 24278556Sobrien 24378556Sobrien int sock = -1; 24478556Sobrien int listen_sock = -1; 24578556Sobrien lldb_private::SocketAddress AcceptAddr; 24678556Sobrien MainLoop accept_loop; 24778556Sobrien std::vector<MainLoopBase::ReadHandleUP> handles; 24878556Sobrien for (auto socket : m_listen_sockets) { 24978556Sobrien auto fd = socket.first; 25078556Sobrien auto inherit = this->m_child_processes_inherit; 25178556Sobrien auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit)); 25278556Sobrien handles.emplace_back(accept_loop.RegisterReadObject( 25378556Sobrien io_sp, [fd, inherit, &sock, &AcceptAddr, &error, 25478556Sobrien &listen_sock](MainLoopBase &loop) { 25578556Sobrien socklen_t sa_len = AcceptAddr.GetMaxLength(); 25678556Sobrien sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit, 25778556Sobrien error); 25878556Sobrien listen_sock = fd; 25978556Sobrien loop.RequestTermination(); 26078556Sobrien }, error)); 26178556Sobrien if (error.Fail()) 26278556Sobrien return error; 26378556Sobrien } 26478556Sobrien 26578556Sobrien bool accept_connection = false; 26678556Sobrien std::unique_ptr<TCPSocket> accepted_socket; 26778556Sobrien // Loop until we are happy with our connection 26878556Sobrien while (!accept_connection) { 26978556Sobrien accept_loop.Run(); 27078556Sobrien 27178556Sobrien if (error.Fail()) 27278556Sobrien return error; 27378556Sobrien 27478556Sobrien lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock]; 27578556Sobrien if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) { 27678556Sobrien CLOSE_SOCKET(sock); 27778556Sobrien llvm::errs() << llvm::formatv( 27878556Sobrien "error: rejecting incoming connection from {0} (expecting {1})", 27978556Sobrien AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress()); 28078556Sobrien continue; 28178556Sobrien } 28278556Sobrien accept_connection = true; 28378556Sobrien accepted_socket.reset(new TCPSocket(sock, *this)); 28478556Sobrien } 28578556Sobrien 28678556Sobrien if (!accepted_socket) 28778556Sobrien return error; 28878556Sobrien 28978556Sobrien // Keep our TCP packets coming without any delays. 29078556Sobrien accepted_socket->SetOptionNoDelay(); 29178556Sobrien error.Clear(); 29278556Sobrien conn_socket = accepted_socket.release(); 29378556Sobrien return error; 29478556Sobrien} 29578556Sobrien 29678556Sobrienint TCPSocket::SetOptionNoDelay() { 29778556Sobrien return SetOption(IPPROTO_TCP, TCP_NODELAY, 1); 29878556Sobrien} 29978556Sobrien 30078556Sobrienint TCPSocket::SetOptionReuseAddress() { 30178556Sobrien return SetOption(SOL_SOCKET, SO_REUSEADDR, 1); 30278556Sobrien} 30378556Sobrien