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