1 //===-- Acceptor.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 "Acceptor.h" 11 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/Support/ScopedPrinter.h" 14 15 #include "lldb/Core/StreamString.h" 16 #include "lldb/Host/ConnectionFileDescriptor.h" 17 #include "lldb/Host/common/TCPSocket.h" 18 19 #include "Utility/UriParser.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 using namespace lldb_private::lldb_server; 24 using namespace llvm; 25 26 namespace { 27 28 struct SocketScheme { 29 const char *m_scheme; 30 const Socket::SocketProtocol m_protocol; 31 }; 32 33 SocketScheme socket_schemes[] = { 34 {"tcp", Socket::ProtocolTcp}, 35 {"udp", Socket::ProtocolUdp}, 36 {"unix", Socket::ProtocolUnixDomain}, 37 {"unix-abstract", Socket::ProtocolUnixAbstract}, 38 }; 39 40 bool FindProtocolByScheme(const char *scheme, 41 Socket::SocketProtocol &protocol) { 42 for (auto s : socket_schemes) { 43 if (!strcmp(s.m_scheme, scheme)) { 44 protocol = s.m_protocol; 45 return true; 46 } 47 } 48 return false; 49 } 50 51 const char *FindSchemeByProtocol(const Socket::SocketProtocol protocol) { 52 for (auto s : socket_schemes) { 53 if (s.m_protocol == protocol) 54 return s.m_scheme; 55 } 56 return nullptr; 57 } 58 } 59 60 Error Acceptor::Listen(int backlog) { 61 return m_listener_socket_up->Listen(StringRef(m_name), backlog); 62 } 63 64 Error Acceptor::Accept(const bool child_processes_inherit, Connection *&conn) { 65 Socket *conn_socket = nullptr; 66 auto error = m_listener_socket_up->Accept( 67 StringRef(m_name), child_processes_inherit, conn_socket); 68 if (error.Success()) 69 conn = new ConnectionFileDescriptor(conn_socket); 70 71 return error; 72 } 73 74 Socket::SocketProtocol Acceptor::GetSocketProtocol() const { 75 return m_listener_socket_up->GetSocketProtocol(); 76 } 77 78 const char *Acceptor::GetSocketScheme() const { 79 return FindSchemeByProtocol(GetSocketProtocol()); 80 } 81 82 std::string Acceptor::GetLocalSocketId() const { return m_local_socket_id(); } 83 84 std::unique_ptr<Acceptor> Acceptor::Create(StringRef name, 85 const bool child_processes_inherit, 86 Error &error) { 87 error.Clear(); 88 89 Socket::SocketProtocol socket_protocol = Socket::ProtocolUnixDomain; 90 int port; 91 StringRef scheme, host, path; 92 // Try to match socket name as URL - e.g., tcp://localhost:5555 93 if (UriParser::Parse(name, scheme, host, port, path)) { 94 if (!FindProtocolByScheme(scheme.str().c_str(), socket_protocol)) 95 error.SetErrorStringWithFormat("Unknown protocol scheme \"%s\"", 96 scheme.str().c_str()); 97 else 98 name = name.drop_front(scheme.size() + strlen("://")); 99 } else { 100 std::string host_str; 101 std::string port_str; 102 int32_t port = INT32_MIN; 103 // Try to match socket name as $host:port - e.g., localhost:5555 104 if (Socket::DecodeHostAndPort(name, host_str, port_str, port, nullptr)) 105 socket_protocol = Socket::ProtocolTcp; 106 } 107 108 if (error.Fail()) 109 return std::unique_ptr<Acceptor>(); 110 111 std::unique_ptr<Socket> listener_socket_up = 112 Socket::Create(socket_protocol, child_processes_inherit, error); 113 114 LocalSocketIdFunc local_socket_id; 115 if (error.Success()) { 116 if (listener_socket_up->GetSocketProtocol() == Socket::ProtocolTcp) { 117 TCPSocket *tcp_socket = 118 static_cast<TCPSocket *>(listener_socket_up.get()); 119 local_socket_id = [tcp_socket]() { 120 auto local_port = tcp_socket->GetLocalPortNumber(); 121 return (local_port != 0) ? llvm::to_string(local_port) : ""; 122 }; 123 } else { 124 const std::string socket_name = name; 125 local_socket_id = [socket_name]() { return socket_name; }; 126 } 127 128 return std::unique_ptr<Acceptor>( 129 new Acceptor(std::move(listener_socket_up), name, local_socket_id)); 130 } 131 132 return std::unique_ptr<Acceptor>(); 133 } 134 135 Acceptor::Acceptor(std::unique_ptr<Socket> &&listener_socket, StringRef name, 136 const LocalSocketIdFunc &local_socket_id) 137 : m_listener_socket_up(std::move(listener_socket)), m_name(name.str()), 138 m_local_socket_id(local_socket_id) {} 139