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 14 #include "lldb/Core/StreamString.h" 15 #include "lldb/Host/ConnectionFileDescriptor.h" 16 #include "lldb/Host/common/TCPSocket.h" 17 18 #include "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 { 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 41 FindProtocolByScheme(const char* scheme, Socket::SocketProtocol& protocol) 42 { 43 for (auto s: socket_schemes) 44 { 45 if (!strcmp(s.m_scheme, scheme)) 46 { 47 protocol = s.m_protocol; 48 return true; 49 } 50 } 51 return false; 52 } 53 54 const char* 55 FindSchemeByProtocol(const Socket::SocketProtocol protocol) 56 { 57 for (auto s: socket_schemes) 58 { 59 if (s.m_protocol == protocol) 60 return s.m_scheme; 61 } 62 return nullptr; 63 } 64 65 } 66 67 Error 68 Acceptor::Listen(int backlog) 69 { 70 return m_listener_socket_up->Listen(StringRef(m_name.c_str()), 71 backlog); 72 } 73 74 Error 75 Acceptor::Accept(const bool child_processes_inherit, Connection *&conn) 76 { 77 Socket* conn_socket = nullptr; 78 auto error = m_listener_socket_up->Accept(StringRef(m_name.c_str()), 79 child_processes_inherit, 80 conn_socket); 81 if (error.Success()) 82 conn = new ConnectionFileDescriptor(conn_socket); 83 84 return error; 85 } 86 87 Socket::SocketProtocol 88 Acceptor::GetSocketProtocol() const 89 { 90 return m_listener_socket_up->GetSocketProtocol(); 91 } 92 93 const char* 94 Acceptor::GetSocketScheme() const 95 { 96 return FindSchemeByProtocol(GetSocketProtocol()); 97 } 98 99 std::string 100 Acceptor::GetLocalSocketId() const 101 { 102 return m_local_socket_id(); 103 } 104 105 std::unique_ptr<Acceptor> 106 Acceptor::Create(StringRef name, const bool child_processes_inherit, Error &error) 107 { 108 error.Clear(); 109 110 Socket::SocketProtocol socket_protocol = Socket::ProtocolUnixDomain; 111 int port; 112 std::string scheme, host, path; 113 // Try to match socket name as URL - e.g., tcp://localhost:5555 114 if (UriParser::Parse(name.str(), scheme, host, port, path)) 115 { 116 if (!FindProtocolByScheme(scheme.c_str(), socket_protocol)) 117 error.SetErrorStringWithFormat("Unknown protocol scheme \"%s\"", scheme.c_str()); 118 else 119 name = name.drop_front(scheme.size() + strlen("://")); 120 } 121 else 122 { 123 std::string host_str; 124 std::string port_str; 125 int32_t port = INT32_MIN; 126 // Try to match socket name as $host:port - e.g., localhost:5555 127 if (Socket::DecodeHostAndPort (name, host_str, port_str, port, nullptr)) 128 socket_protocol = Socket::ProtocolTcp; 129 } 130 131 if (error.Fail()) 132 return std::unique_ptr<Acceptor>(); 133 134 std::unique_ptr<Socket> listener_socket_up = Socket::Create( 135 socket_protocol, child_processes_inherit, error); 136 137 LocalSocketIdFunc local_socket_id; 138 if (error.Success()) 139 { 140 if (listener_socket_up->GetSocketProtocol() == Socket::ProtocolTcp) 141 { 142 TCPSocket* tcp_socket = static_cast<TCPSocket*>(listener_socket_up.get()); 143 local_socket_id = [tcp_socket]() { 144 auto local_port = tcp_socket->GetLocalPortNumber(); 145 return (local_port != 0) ? std::to_string(local_port) : ""; 146 }; 147 } 148 else 149 { 150 const std::string socket_name = name; 151 local_socket_id = [socket_name](){ 152 return socket_name; 153 }; 154 } 155 156 return std::unique_ptr<Acceptor>( 157 new Acceptor(std::move(listener_socket_up), name, local_socket_id)); 158 } 159 160 return std::unique_ptr<Acceptor>(); 161 } 162 163 Acceptor::Acceptor(std::unique_ptr<Socket> &&listener_socket, 164 StringRef name, 165 const LocalSocketIdFunc &local_socket_id) 166 : m_listener_socket_up(std::move(listener_socket)), 167 m_name(name.str()), 168 m_local_socket_id(local_socket_id) 169 { 170 } 171