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