diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Host/common/Socket.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Host/common/Socket.cpp | 622 |
1 files changed, 172 insertions, 450 deletions
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp b/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp index f7e93c634a12..91a5e37424e6 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp @@ -12,21 +12,16 @@ #include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Host/Config.h" -#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/SocketAddress.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" - -#ifdef __ANDROID_NDK__ -#include <linux/tcp.h> -#include <bits/error_constants.h> -#include <asm-generic/errno-base.h> -#include <errno.h> -#include <arpa/inet.h> -#endif +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Host/common/UDPSocket.h" #ifndef LLDB_DISABLE_POSIX +#include "lldb/Host/posix/DomainSocket.h" + #include <arpa/inet.h> #include <netdb.h> #include <netinet/in.h> @@ -35,6 +30,23 @@ #include <sys/un.h> #endif +#ifdef __linux__ +#include "lldb/Host/linux/AbstractSocket.h" +#endif + +#ifdef __ANDROID_NDK__ +#include <linux/tcp.h> +#include <bits/error_constants.h> +#include <asm-generic/errno-base.h> +#include <errno.h> +#include <arpa/inet.h> +#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC) +#include <unistd.h> +#include <sys/syscall.h> +#include <fcntl.h> +#endif // ANDROID_ARM_BUILD_STATIC || ANDROID_MIPS_BUILD_STATIC +#endif // __ANDROID_NDK__ + using namespace lldb; using namespace lldb_private; @@ -48,48 +60,8 @@ typedef void * get_socket_option_arg_type; const NativeSocket Socket::kInvalidSocketValue = -1; #endif // #if defined(_WIN32) -#ifdef __ANDROID__ -// Android does not have SUN_LEN -#ifndef SUN_LEN -#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path)) -#endif -#endif // #ifdef __ANDROID__ - namespace { -NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit) -{ - auto socketType = type; -#ifdef SOCK_CLOEXEC - if (!child_processes_inherit) { - socketType |= SOCK_CLOEXEC; - } -#endif - return ::socket (domain, socketType, protocol); -} - -NativeSocket Accept(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit) -{ -#ifdef SOCK_CLOEXEC - int flags = 0; - if (!child_processes_inherit) { - flags |= SOCK_CLOEXEC; - } - return ::accept4 (sockfd, addr, addrlen, flags); -#else - return ::accept (sockfd, addr, addrlen); -#endif -} - -void SetLastError(Error &error) -{ -#if defined(_WIN32) - error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32); -#else - error.SetErrorToErrno(); -#endif -} - bool IsInterrupted() { #if defined(_WIN32) @@ -114,128 +86,84 @@ Socket::~Socket() Close(); } -Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) +std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, bool child_processes_inherit, Error &error) { - // Store the result in a unique_ptr in case we error out, the memory will get correctly freed. - std::unique_ptr<Socket> final_socket; - NativeSocket sock = kInvalidSocketValue; - Error error; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST)); - if (log) - log->Printf ("Socket::TcpConnect (host/port = %s)", host_and_port.data()); - - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error)) - return error; - - // Create the socket - sock = CreateSocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, child_processes_inherit); - if (sock == kInvalidSocketValue) - { - SetLastError (error); - return error; - } - - // Since they both refer to the same socket descriptor, arbitrarily choose the send socket to - // be the owner. - final_socket.reset(new Socket(sock, ProtocolTcp, true)); - - // Enable local address reuse - final_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1); - - struct sockaddr_in sa; - ::memset (&sa, 0, sizeof (sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons (port); - - int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); + error.Clear(); - if (inet_pton_result <= 0) + std::unique_ptr<Socket> socket_up; + switch (protocol) { - struct hostent *host_entry = gethostbyname (host_str.c_str()); - if (host_entry) - host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); - inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); - if (inet_pton_result <= 0) - { - if (inet_pton_result == -1) - SetLastError(error); - else - error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str()); - - return error; - } + case ProtocolTcp: + socket_up.reset(new TCPSocket(child_processes_inherit, error)); + break; + case ProtocolUdp: + socket_up.reset(new UDPSocket(child_processes_inherit, error)); + break; + case ProtocolUnixDomain: +#ifndef LLDB_DISABLE_POSIX + socket_up.reset(new DomainSocket(child_processes_inherit, error)); +#else + error.SetErrorString("Unix domain sockets are not supported on this platform."); +#endif + break; + case ProtocolUnixAbstract: +#ifdef __linux__ + socket_up.reset(new AbstractSocket(child_processes_inherit, error)); +#else + error.SetErrorString("Abstract domain sockets are not supported on this platform."); +#endif + break; } - if (-1 == ::connect (sock, (const struct sockaddr *)&sa, sizeof(sa))) - { - SetLastError (error); - return error; - } + if (error.Fail()) + socket_up.reset(); - // Keep our TCP packets coming without any delays. - final_socket->SetOption(IPPROTO_TCP, TCP_NODELAY, 1); - error.Clear(); - socket = final_socket.release(); - return error; + return socket_up; } -Error Socket::TcpListen( - llvm::StringRef host_and_port, - bool child_processes_inherit, - Socket *&socket, - Predicate<uint16_t>* predicate, - int backlog) +Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { - std::unique_ptr<Socket> listen_socket; - NativeSocket listen_sock = kInvalidSocketValue; - Error error; + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); + if (log) + log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data()); - const sa_family_t family = AF_INET; - const int socktype = SOCK_STREAM; - const int protocol = IPPROTO_TCP; - listen_sock = ::CreateSocket (family, socktype, protocol, child_processes_inherit); - if (listen_sock == kInvalidSocketValue) - { - SetLastError (error); + Error error; + std::unique_ptr<Socket> connect_socket(Create(ProtocolTcp, child_processes_inherit, error)); + if (error.Fail()) return error; - } - listen_socket.reset(new Socket(listen_sock, ProtocolTcp, true)); + error = connect_socket->Connect(host_and_port); + if (error.Success()) + socket = connect_socket.release(); - // enable local address reuse - listen_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1); + return error; +} +Error +Socket::TcpListen (llvm::StringRef host_and_port, + bool child_processes_inherit, + Socket *&socket, + Predicate<uint16_t>* predicate, + int backlog) +{ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf ("Socket::TcpListen (%s)", host_and_port.data()); + log->Printf ("Socket::%s (%s)", __FUNCTION__, host_and_port.data()); + Error error; std::string host_str; std::string port_str; int32_t port = INT32_MIN; if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error)) return error; - SocketAddress anyaddr; - if (anyaddr.SetToAnyAddress (family, port)) - { - int err = ::bind (listen_sock, anyaddr, anyaddr.GetLength()); - if (err == -1) - { - SetLastError (error); - return error; - } - - err = ::listen (listen_sock, backlog); - if (err == -1) - { - SetLastError (error); - return error; - } + std::unique_ptr<TCPSocket> listen_socket(new TCPSocket(child_processes_inherit, error)); + if (error.Fail()) + return error; + error = listen_socket->Listen(host_and_port, backlog); + if (error.Success()) + { // We were asked to listen on port zero which means we // must now read the actual port that was given to us // as port zero is a special code for "find an open port @@ -250,287 +178,77 @@ Error Socket::TcpListen( // another thread in an efficient manor. if (predicate) predicate->SetValue (port, eBroadcastAlways); - socket = listen_socket.release(); } return error; } -Error Socket::BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) -{ - Error error; - std::string host_str; - std::string port_str; - int32_t port; - if (!DecodeHostAndPort(host_and_port, host_str, port_str, port, &error)) - return error; - - const sa_family_t family = AF_INET; - const int socktype = SOCK_STREAM; - const int protocol = IPPROTO_TCP; - SocketAddress listen_addr; - if (host_str.empty()) - listen_addr.SetToLocalhost(family, port); - else if (host_str.compare("*") == 0) - listen_addr.SetToAnyAddress(family, port); - else - { - if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol)) - { - error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str()); - return error; - } - } - - bool accept_connection = false; - std::unique_ptr<Socket> accepted_socket; - - // Loop until we are happy with our connection - while (!accept_connection) - { - struct sockaddr_in accept_addr; - ::memset (&accept_addr, 0, sizeof accept_addr); -#if !(defined (__linux__) || defined(_WIN32)) - accept_addr.sin_len = sizeof accept_addr; -#endif - socklen_t accept_addr_len = sizeof accept_addr; - - int sock = Accept (this->GetNativeSocket(), - (struct sockaddr *)&accept_addr, - &accept_addr_len, - child_processes_inherit); - - if (sock == kInvalidSocketValue) - { - SetLastError (error); - break; - } - - bool is_same_addr = true; -#if !(defined(__linux__) || (defined(_WIN32))) - is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len); -#endif - if (is_same_addr) - is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr); - - if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) - { - accept_connection = true; - // Since both sockets have the same descriptor, arbitrarily choose the send - // socket to be the owner. - accepted_socket.reset(new Socket(sock, ProtocolTcp, true)); - } - else - { - const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; - const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr; - ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", - accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], - listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); - accepted_socket.reset(); - } - } - - if (!accepted_socket) - return error; - - // Keep our TCP packets coming without any delays. - accepted_socket->SetOption (IPPROTO_TCP, TCP_NODELAY, 1); - error.Clear(); - socket = accepted_socket.release(); - return error; - -} - Error Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket) { - std::unique_ptr<Socket> final_send_socket; - std::unique_ptr<Socket> final_recv_socket; - NativeSocket final_send_fd = kInvalidSocketValue; - NativeSocket final_recv_fd = kInvalidSocketValue; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf ("Socket::UdpConnect (host/port = %s)", host_and_port.data()); + log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data()); + return UDPSocket::Connect(host_and_port, child_processes_inherit, send_socket, recv_socket); +} + +Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ Error error; - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error)) + std::unique_ptr<Socket> connect_socket(Create(ProtocolUnixDomain, child_processes_inherit, error)); + if (error.Fail()) return error; - // Setup the receiving end of the UDP connection on this localhost - // on port zero. After we bind to port zero we can read the port. - final_recv_fd = ::CreateSocket (AF_INET, SOCK_DGRAM, 0, child_processes_inherit); - if (final_recv_fd == kInvalidSocketValue) - { - // Socket creation failed... - SetLastError (error); - } - else - { - final_recv_socket.reset(new Socket(final_recv_fd, ProtocolUdp, true)); - - // Socket was created, now lets bind to the requested port - SocketAddress addr; - addr.SetToAnyAddress (AF_INET, 0); + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); - if (::bind (final_recv_fd, addr, addr.GetLength()) == -1) - { - // Bind failed... - SetLastError (error); - } - } + return error; +} - assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid())); +Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ + Error error; + std::unique_ptr<Socket> listen_socket(Create(ProtocolUnixDomain, child_processes_inherit, error)); if (error.Fail()) return error; - // At this point we have setup the receive port, now we need to - // setup the UDP send socket - - struct addrinfo hints; - struct addrinfo *service_info_list = NULL; - - ::memset (&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; - int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list); - if (err != 0) - { - error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)", - host_str.c_str(), - port_str.c_str(), - err, - gai_strerror(err)); - return error; - } - - for (struct addrinfo *service_info_ptr = service_info_list; - service_info_ptr != NULL; - service_info_ptr = service_info_ptr->ai_next) - { - final_send_fd = ::CreateSocket (service_info_ptr->ai_family, - service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol, - child_processes_inherit); - - if (final_send_fd != kInvalidSocketValue) - { - final_send_socket.reset(new Socket(final_send_fd, ProtocolUdp, true)); - final_send_socket->m_udp_send_sockaddr = service_info_ptr; - break; - } - else - continue; - } - - :: freeaddrinfo (service_info_list); - - if (final_send_fd == kInvalidSocketValue) - { - SetLastError (error); + error = listen_socket->Listen(name, 5); + if (error.Fail()) return error; - } - send_socket = final_send_socket.release(); - recv_socket = final_recv_socket.release(); - error.Clear(); + error = listen_socket->Accept(name, child_processes_inherit, socket); return error; } -Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +Error +Socket::UnixAbstractConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; -#ifndef LLDB_DISABLE_POSIX - std::unique_ptr<Socket> final_socket; - - // Open the socket that was passed in as an option - struct sockaddr_un saddr_un; - int fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); - if (fd == kInvalidSocketValue) - { - SetLastError (error); - return error; - } - - final_socket.reset(new Socket(fd, ProtocolUnixDomain, true)); - - saddr_un.sun_family = AF_UNIX; - ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1); - saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - saddr_un.sun_len = SUN_LEN (&saddr_un); -#endif - - if (::connect (fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0) - { - SetLastError (error); + std::unique_ptr<Socket> connect_socket(Create(ProtocolUnixAbstract, child_processes_inherit, error)); + if (error.Fail()) return error; - } - socket = final_socket.release(); -#else - error.SetErrorString("Unix domain sockets are not supported on this platform."); -#endif + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); return error; } -Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +Error +Socket::UnixAbstractAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; -#ifndef LLDB_DISABLE_POSIX - struct sockaddr_un saddr_un; - std::unique_ptr<Socket> listen_socket; - std::unique_ptr<Socket> final_socket; - NativeSocket listen_fd = kInvalidSocketValue; - NativeSocket socket_fd = kInvalidSocketValue; - - listen_fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); - if (listen_fd == kInvalidSocketValue) - { - SetLastError (error); + std::unique_ptr<Socket> listen_socket(Create(ProtocolUnixAbstract,child_processes_inherit, error)); + if (error.Fail()) return error; - } - - listen_socket.reset(new Socket(listen_fd, ProtocolUnixDomain, true)); - - saddr_un.sun_family = AF_UNIX; - ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1); - saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - saddr_un.sun_len = SUN_LEN (&saddr_un); -#endif - FileSystem::Unlink(FileSpec{name, true}); - bool success = false; - if (::bind (listen_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0) - { - if (::listen (listen_fd, 5) == 0) - { - socket_fd = Accept (listen_fd, NULL, 0, child_processes_inherit); - if (socket_fd > 0) - { - final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true)); - success = true; - } - } - } - - if (!success) - { - SetLastError (error); + error = listen_socket->Listen(name, 5); + if (error.Fail()) return error; - } - // We are done with the listen port - listen_socket.reset(); - socket = final_socket.release(); -#else - error.SetErrorString("Unix domain sockets are not supported on this platform."); -#endif + error = listen_socket->Accept(name, child_processes_inherit, socket); return error; } @@ -605,7 +323,7 @@ Error Socket::Read (void *buf, size_t &num_bytes) else num_bytes = bytes_received; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_COMMUNICATION)); + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); if (log) { log->Printf ("%p Socket::Read() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)", @@ -626,17 +344,7 @@ Error Socket::Write (const void *buf, size_t &num_bytes) int bytes_sent = 0; do { - if (m_protocol == ProtocolUdp) - { - bytes_sent = ::sendto (m_socket, - static_cast<const char*>(buf), - num_bytes, - 0, - m_udp_send_sockaddr, - m_udp_send_sockaddr.GetLength()); - } - else - bytes_sent = ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0); + bytes_sent = Send(buf, num_bytes); } while (bytes_sent < 0 && IsInterrupted ()); if (bytes_sent < 0) @@ -647,7 +355,7 @@ Error Socket::Write (const void *buf, size_t &num_bytes) else num_bytes = bytes_sent; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST)); + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); if (log) { log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)", @@ -698,70 +406,84 @@ int Socket::GetOption(int level, int option_name, int &option_value) { get_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value); socklen_t option_value_size = sizeof(int); - return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size); + return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size); } int Socket::SetOption(int level, int option_name, int option_value) { set_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value); - return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); + return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); } -uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket) +size_t Socket::Send(const void *buf, const size_t num_bytes) { - // We bound to port zero, so we need to figure out which port we actually bound to - if (socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getsockname (socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetPort (); - } - return 0; + return ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0); } -// Return the port number that is being used by the socket. -uint16_t Socket::GetLocalPortNumber() const +void Socket::SetLastError(Error &error) { - return GetLocalPortNumber (m_socket); +#if defined(_WIN32) + error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32); +#else + error.SetErrorToErrno(); +#endif } -std::string Socket::GetLocalIPAddress () const +NativeSocket +Socket::CreateSocket(const int domain, + const int type, + const int protocol, + bool child_processes_inherit, + Error& error) { - // We bound to port zero, so we need to figure out which port we actually bound to - if (m_socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetIPAddress (); - } - return ""; -} + error.Clear(); + auto socketType = type; +#ifdef SOCK_CLOEXEC + if (!child_processes_inherit) + socketType |= SOCK_CLOEXEC; +#endif + auto sock = ::socket (domain, socketType, protocol); + if (sock == kInvalidSocketValue) + SetLastError(error); -uint16_t Socket::GetRemotePortNumber () const -{ - if (m_socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetPort (); - } - return 0; + return sock; } -std::string Socket::GetRemoteIPAddress () const +NativeSocket +Socket::AcceptSocket(NativeSocket sockfd, + struct sockaddr *addr, + socklen_t *addrlen, + bool child_processes_inherit, + Error& error) { - // We bound to port zero, so we need to figure out which port we actually bound to - if (m_socket != kInvalidSocketValue) + error.Clear(); +#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC) + // Temporary workaround for statically linking Android lldb-server with the + // latest API. + int fd = syscall(__NR_accept, sockfd, addr, addrlen); + if (fd >= 0 && !child_processes_inherit) { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetIPAddress (); + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1 && ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1) + return fd; + SetLastError(error); + close(fd); + } + return fd; +#elif defined(SOCK_CLOEXEC) + int flags = 0; + if (!child_processes_inherit) { + flags |= SOCK_CLOEXEC; } - return ""; +#if defined(__NetBSD__) + NativeSocket fd = ::paccept (sockfd, addr, addrlen, nullptr, flags); +#else + NativeSocket fd = ::accept4 (sockfd, addr, addrlen, flags); +#endif +#else + NativeSocket fd = ::accept (sockfd, addr, addrlen); +#endif + if (fd == kInvalidSocketValue) + SetLastError(error); + return fd; } - - |