mgorny updated this revision to Diff 381645.
mgorny retitled this revision from "[lldb] [lldb-server] Allow any protocol
supported by lldb" to "[lldb] [lldb-gdbserver] Unify listen/connect code to use
ConnectionFileDescriptor".
mgorny edited the summary of this revision.
mgorny added a comment.
Turned it into an überpatch upgrading CFD and refactoring lldb-server to reduce
duplication of code.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D111964/new/
https://reviews.llvm.org/D111964
Files:
lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
lldb/test/API/tools/lldb-server/TestPtyServer.py
lldb/tools/lldb-server/lldb-gdbserver.cpp
lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
Index: lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
===================================================================
--- lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
+++ lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
@@ -43,3 +43,62 @@
return;
TestGetURI("::1");
}
+
+TEST(ConnectionFileDescriptorUtilityTest, LLGSArgToURL) {
+ // LLGS new-style URLs should be passed through (indepenently of
+ // --reverse-connect)
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("listen://127.0.0.1:1234", false),
+ llvm::HasValue("listen://127.0.0.1:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("listen://127.0.0.1:1234", true),
+ llvm::HasValue("listen://127.0.0.1:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("connect://127.0.0.1:1234", false),
+ llvm::HasValue("connect://127.0.0.1:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("connect://127.0.0.1:1234", true),
+ llvm::HasValue("connect://127.0.0.1:1234"));
+
+ // LLGS legacy listen URLs should be converted if !reverse_connect
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("tcp://127.0.0.1:1234", false),
+ llvm::HasValue("listen://127.0.0.1:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("unix:///tmp/foo", false),
+ llvm::HasValue("unix-accept:///tmp/foo"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("unix-abstract://foo", false),
+ llvm::HasValue("unix-abstract-accept://foo"));
+
+ // LLGS listen host:port pairs should be converted to listen://
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("127.0.0.1:1234", false),
+ llvm::HasValue("listen://127.0.0.1:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("[::1]:1234", false),
+ llvm::HasValue("listen://[::1]:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("[[::1]:1234]", false),
+ llvm::HasValue("listen://[[::1]:1234]"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("localhost:1234", false),
+ llvm::HasValue("listen://localhost:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("*:1234", false),
+ llvm::HasValue("listen://*:1234"));
+
+ // LLGS listen :port special-case should be converted to listen://
+ EXPECT_THAT_EXPECTED(LLGSArgToURL(":1234", false),
+ llvm::HasValue("listen://localhost:1234"));
+
+ // LLGS listen UNIX sockets should be converted to unix-accept://
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("/tmp/foo", false),
+ llvm::HasValue("unix-accept:///tmp/foo"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("127.0.0.1", false),
+ llvm::HasValue("unix-accept://127.0.0.1"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("[::1]", false),
+ llvm::HasValue("unix-accept://[::1]"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("localhost", false),
+ llvm::HasValue("unix-accept://localhost"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL(":frobnicate", false),
+ llvm::HasValue("unix-accept://:frobnicate"));
+
+ // LLGS reverse connect host:port pairs should be converted to listen://
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("127.0.0.1:1234", true),
+ llvm::HasValue("connect://127.0.0.1:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("[::1]:1234", true),
+ llvm::HasValue("connect://[::1]:1234"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("[[::1]:1234]", true),
+ llvm::HasValue("connect://[[::1]:1234]"));
+ EXPECT_THAT_EXPECTED(LLGSArgToURL("localhost:1234", true),
+ llvm::HasValue("connect://localhost:1234"));
+}
Index: lldb/tools/lldb-server/lldb-gdbserver.cpp
===================================================================
--- lldb/tools/lldb-server/lldb-gdbserver.cpp
+++ lldb/tools/lldb-server/lldb-gdbserver.cpp
@@ -17,7 +17,6 @@
#include <unistd.h>
#endif
-#include "Acceptor.h"
#include "LLDBServerUtilities.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
@@ -164,15 +163,14 @@
}
}
-Status writeSocketIdToPipe(Pipe &port_pipe, const std::string &socket_id) {
+Status writeSocketIdToPipe(Pipe &port_pipe, llvm::StringRef socket_id) {
size_t bytes_written = 0;
// Write the port number as a C string with the NULL terminator.
- return port_pipe.Write(socket_id.c_str(), socket_id.size() + 1,
- bytes_written);
+ return port_pipe.Write(socket_id.data(), socket_id.size() + 1, bytes_written);
}
Status writeSocketIdToPipe(const char *const named_pipe_path,
- const std::string &socket_id) {
+ llvm::StringRef socket_id) {
Pipe port_name_pipe;
// Wait for 10 seconds for pipe to be opened.
auto error = port_name_pipe.OpenAsWriterWithTimeout(named_pipe_path, false,
@@ -183,7 +181,7 @@
}
Status writeSocketIdToPipe(lldb::pipe_t unnamed_pipe,
- const std::string &socket_id) {
+ llvm::StringRef socket_id) {
Pipe port_pipe{LLDB_INVALID_PIPE, unnamed_pipe};
return writeSocketIdToPipe(port_pipe, socket_id);
}
@@ -197,120 +195,74 @@
Status error;
std::unique_ptr<Connection> connection_up;
+ std::string url;
+
if (connection_fd != -1) {
- // Build the connection string.
- std::string connection_url = llvm::formatv("fd://{0}", connection_fd).str();
+ url = llvm::formatv("fd://{0}", connection_fd).str();
// Create the connection.
#if LLDB_ENABLE_POSIX && !defined _WIN32
::fcntl(connection_fd, F_SETFD, FD_CLOEXEC);
#endif
- connection_up.reset(new ConnectionFileDescriptor);
- auto connection_result = connection_up->Connect(connection_url, &error);
+ } else if (!host_and_port.empty()) {
+ llvm::Expected<std::string> url_exp =
+ LLGSArgToURL(host_and_port, reverse_connect);
+ if (!url_exp) {
+ llvm::errs() << llvm::formatv("error: invalid host:port or URL '{0}': "
+ "{1}\n",
+ host_and_port,
+ llvm::toString(url_exp.takeError()));
+ exit(-1);
+ }
+
+ url = std::move(url_exp.get());
+ }
+
+ if (!url.empty()) {
+ // Create the connection or server.
+ std::unique_ptr<ConnectionFileDescriptor> conn_fd_up{
+ new ConnectionFileDescriptor};
+ auto connection_result = conn_fd_up->Connect(
+ url,
+ [named_pipe_path, unnamed_pipe](llvm::StringRef socket_id) {
+ if (!socket_id.empty()) {
+ // If we have a named pipe to write the socket id back to, do that
+ // now.
+ if (named_pipe_path && named_pipe_path[0]) {
+ Status error = writeSocketIdToPipe(named_pipe_path, socket_id);
+ if (error.Fail())
+ llvm::errs() << llvm::formatv(
+ "failed to write to the named peipe '{0}': {1}\n",
+ named_pipe_path, error.AsCString());
+ }
+ // If we have an unnamed pipe to write the socket id back to, do
+ // that now.
+ else if (unnamed_pipe != LLDB_INVALID_PIPE) {
+ Status error = writeSocketIdToPipe(unnamed_pipe, socket_id);
+ if (error.Fail())
+ llvm::errs() << llvm::formatv(
+ "failed to write to the unnamed pipe: {0}\n", error);
+ }
+ } else {
+ llvm::errs() << "unable to get the socket id for the listening "
+ "connection\n";
+ }
+ },
+ &error);
+
if (error.Fail()) {
llvm::errs() << llvm::formatv(
- "error: failed to connect to client at '{0}': {1}\n", connection_url,
- error);
+ "error: failed to connect to client at '{0}': {1}\n", url, error);
exit(-1);
}
if (connection_result != eConnectionStatusSuccess) {
llvm::errs() << llvm::formatv(
"error: failed to connect to client at '{0}' "
"(connection status: {1})\n",
- connection_url, static_cast<int>(connection_result));
+ url, static_cast<int>(connection_result));
exit(-1);
}
- } else if (!host_and_port.empty()) {
- // Parse out host and port.
- std::string final_host_and_port;
-
- // If host_and_port starts with ':', default the host to be "localhost" and
- // expect the remainder to be the port.
- if (host_and_port[0] == ':')
- final_host_and_port.append("localhost");
- final_host_and_port.append(host_and_port.str());
-
- if (reverse_connect) {
- // llgs will connect to the gdb-remote client.
-
- // Ensure we have a port number for the connection.
- // Note: use rfind, because the host/port may look like "[::1]:12345".
- uint32_t connection_portno = 0;
- const std::string::size_type colon_pos = final_host_and_port.rfind(':');
- if (colon_pos != std::string::npos)
- llvm::to_integer(final_host_and_port.substr(colon_pos + 1),
- connection_portno);
- if (connection_portno == 0) {
- llvm::errs() << "error: port number must be specified on when using "
- "reverse connect\n";
- exit(1);
- }
-
- // Build the connection string.
- final_host_and_port.insert(0, "connect://");
-
- // Create the connection.
- connection_up.reset(new ConnectionFileDescriptor);
- auto connection_result =
- connection_up->Connect(final_host_and_port, &error);
- if (error.Fail()) {
- llvm::errs() << llvm::formatv(
- "error: failed to connect to client at '{0}': {1}\n",
- final_host_and_port, error);
- exit(-1);
- }
- if (connection_result != eConnectionStatusSuccess) {
- llvm::errs() << llvm::formatv(
- "error: failed to connect to client at '{0}' "
- "(connection status: {1})\n",
- final_host_and_port, static_cast<int>(connection_result));
- exit(-1);
- }
- } else {
- std::unique_ptr<Acceptor> acceptor_up(
- Acceptor::Create(final_host_and_port, false, error));
- if (error.Fail()) {
- llvm::errs() << llvm::formatv("failed to create acceptor: {0}\n",
- error);
- exit(1);
- }
- error = acceptor_up->Listen(1);
- if (error.Fail()) {
- llvm::errs() << llvm::formatv("failed to listen: {0}\n", error);
- exit(1);
- }
- const std::string socket_id = acceptor_up->GetLocalSocketId();
- if (!socket_id.empty()) {
- // If we have a named pipe to write the socket id back to, do that now.
- if (named_pipe_path && named_pipe_path[0]) {
- error = writeSocketIdToPipe(named_pipe_path, socket_id);
- if (error.Fail())
- llvm::errs() << llvm::formatv(
- "failed to write to the named peipe '{0}': {1}\n",
- named_pipe_path, error.AsCString());
- }
- // If we have an unnamed pipe to write the socket id back to, do that
- // now.
- else if (unnamed_pipe != LLDB_INVALID_PIPE) {
- error = writeSocketIdToPipe(unnamed_pipe, socket_id);
- if (error.Fail())
- llvm::errs() << llvm::formatv(
- "failed to write to the unnamed pipe: {0}\n", error);
- }
- } else {
- llvm::errs()
- << "unable to get the socket id for the listening connection\n";
- }
-
- Connection *conn = nullptr;
- error = acceptor_up->Accept(false, conn);
- if (error.Fail()) {
- llvm::errs() << llvm::formatv("failed to accept new connection: {0}\n",
- error);
- exit(1);
- }
- connection_up.reset(conn);
- }
+ connection_up = std::move(conn_fd_up);
}
error = gdb_server.InitializeConnection(std::move(connection_up));
if (error.Fail()) {
Index: lldb/test/API/tools/lldb-server/TestPtyServer.py
===================================================================
--- /dev/null
+++ lldb/test/API/tools/lldb-server/TestPtyServer.py
@@ -0,0 +1,73 @@
+import gdbremote_testcase
+import lldbgdbserverutils
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbgdbserverutils import *
+
+import xml.etree.ElementTree as ET
+
+
+@skipIfWindows
+class PtyServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ super().setUp()
+ import pty
+ import tty
+ master, slave = pty.openpty()
+ tty.setraw(master)
+ self._master = io.FileIO(master, 'r+b')
+ self._slave = io.FileIO(slave, 'r+b')
+
+ def get_debug_monitor_command_line_args(self, attach_pid=None):
+ commandline_args = self.debug_monitor_extra_args
+ if attach_pid:
+ commandline_args += ["--attach=%d" % attach_pid]
+
+ libc = ctypes.CDLL(None)
+ libc.ptsname.argtypes = (ctypes.c_int,)
+ libc.ptsname.restype = ctypes.c_char_p
+ pty_path = libc.ptsname(self._master.fileno()).decode()
+ commandline_args += ["serial://%s" % (pty_path,)]
+ return commandline_args
+
+ def connect_to_debug_monitor(self, attach_pid=None):
+ self.reverse_connect = False
+ server = self.launch_debug_monitor(attach_pid=attach_pid)
+ self.assertIsNotNone(server)
+
+ # TODO: make it into proper abstraction
+ class FakeSocket:
+ def __init__(self, fd):
+ self.fd = fd
+
+ def sendall(self, frame):
+ self.fd.write(frame)
+
+ def recv(self, count):
+ return self.fd.read(count)
+
+ self.sock = FakeSocket(self._master)
+ self._server = Server(self.sock, server)
+ return server
+
+ @add_test_categories(["llgs"])
+ def test_pty_server(self):
+ self.build()
+ self.set_inferior_startup_launch()
+ self.prep_debug_monitor_and_inferior()
+
+ # target.xml transfer should trigger a large enough packet to check
+ # for partial write regression
+ self.test_sequence.add_log_lines([
+ "read packet: $qXfer:features:read:target.xml:0,200000#00",
+ {
+ "direction": "send",
+ "regex": re.compile("^\$l(.+)#[0-9a-fA-F]{2}$"),
+ "capture": {1: "target_xml"},
+ }],
+ True)
+ context = self.expect_gdbremote_sequence()
+ # verify that we have received a complete, non-malformed XML
+ self.assertIsNotNone(ET.fromstring(context.get("target_xml")))
Index: lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
===================================================================
--- lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -13,12 +13,13 @@
#define _DARWIN_UNLIMITED_SELECT
#endif
-#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/Socket.h"
#include "lldb/Host/SocketAddress.h"
+#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
#include "lldb/Utility/SelectHelper.h"
#include "lldb/Utility/Timeout.h"
+#include "lldb/Utility/UriParser.h"
#include <cerrno>
#include <cstdlib>
@@ -62,7 +63,7 @@
ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd)
: Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
- m_waiting_for_accept(false), m_child_processes_inherit(false) {
+ m_child_processes_inherit(false) {
m_io_sp =
std::make_shared<NativeFile>(fd, File::eOpenOptionReadWrite, owns_fd);
@@ -77,7 +78,7 @@
ConnectionFileDescriptor::ConnectionFileDescriptor(Socket *socket)
: Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
- m_waiting_for_accept(false), m_child_processes_inherit(false) {
+ m_child_processes_inherit(false) {
InitializeSocket(socket);
}
@@ -124,6 +125,13 @@
ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path,
Status *error_ptr) {
+ return Connect(path, nullptr, error_ptr);
+}
+
+ConnectionStatus ConnectionFileDescriptor::Connect(
+ llvm::StringRef path,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
LLDB_LOGF(log, "%p ConnectionFileDescriptor::Connect (url = '%s')",
@@ -143,10 +151,14 @@
if (!path.empty()) {
auto method =
llvm::StringSwitch<ConnectionStatus (ConnectionFileDescriptor::*)(
- llvm::StringRef, Status *)>(scheme)
+ llvm::StringRef,
+ std::function<void(llvm::StringRef local_socket_id)>, Status *)>(
+ scheme)
.Case("listen", &ConnectionFileDescriptor::SocketListenAndAccept)
.Cases("accept", "unix-accept",
&ConnectionFileDescriptor::NamedSocketAccept)
+ .Case("unix-abstract-accept",
+ &ConnectionFileDescriptor::UnixAbstractSocketAccept)
.Cases("connect", "tcp-connect",
&ConnectionFileDescriptor::ConnectTCP)
.Case("udp", &ConnectionFileDescriptor::ConnectUDP)
@@ -161,7 +173,7 @@
.Default(nullptr);
if (method)
- return (this->*method)(path, error_ptr);
+ return (this->*method)(path, socket_id_callback, error_ptr);
}
if (error_ptr)
@@ -498,7 +510,8 @@
// data from that pipe:
char c;
- ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1);
+ ssize_t bytes_read =
+ llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1);
assert(bytes_read == 1);
(void)bytes_read;
switch (c) {
@@ -522,24 +535,39 @@
return eConnectionStatusLostConnection;
}
-ConnectionStatus
-ConnectionFileDescriptor::NamedSocketAccept(llvm::StringRef socket_name,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::NamedSocketAccept(
+ llvm::StringRef socket_name,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
+ Status error;
+ std::unique_ptr<Socket> listen_socket = Socket::Create(
+ Socket::ProtocolUnixDomain, m_child_processes_inherit, error);
Socket *socket = nullptr;
- Status error =
- Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket);
+
+ if (!error.Fail())
+ error = listen_socket->Listen(socket_name, 5);
+
+ if (!error.Fail())
+ socket_id_callback(socket_name);
+
+ if (!error.Fail())
+ error = listen_socket->Accept(socket);
+
+ if (!error.Fail()) {
+ m_io_sp.reset(socket);
+ m_uri.assign(socket_name.str());
+ return eConnectionStatusSuccess;
+ }
+
if (error_ptr)
*error_ptr = error;
- m_io_sp.reset(socket);
- if (error.Fail())
- return eConnectionStatusError;
- m_uri.assign(std::string(socket_name));
- return eConnectionStatusSuccess;
+ return eConnectionStatusError;
}
-ConnectionStatus
-ConnectionFileDescriptor::NamedSocketConnect(llvm::StringRef socket_name,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::NamedSocketConnect(
+ llvm::StringRef socket_name,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
Socket *socket = nullptr;
Status error =
Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket);
@@ -552,9 +580,39 @@
return eConnectionStatusSuccess;
}
-lldb::ConnectionStatus
-ConnectionFileDescriptor::UnixAbstractSocketConnect(llvm::StringRef socket_name,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::UnixAbstractSocketAccept(
+ llvm::StringRef socket_name,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
+ Status error;
+ std::unique_ptr<Socket> listen_socket = Socket::Create(
+ Socket::ProtocolUnixAbstract, m_child_processes_inherit, error);
+ Socket *socket = nullptr;
+
+ if (!error.Fail())
+ error = listen_socket->Listen(socket_name, 5);
+
+ if (!error.Fail())
+ socket_id_callback(socket_name);
+
+ if (!error.Fail())
+ error = listen_socket->Accept(socket);
+
+ if (!error.Fail()) {
+ m_io_sp.reset(socket);
+ m_uri.assign(socket_name.str());
+ return eConnectionStatusSuccess;
+ }
+
+ if (error_ptr)
+ *error_ptr = error;
+ return eConnectionStatusError;
+}
+
+lldb::ConnectionStatus ConnectionFileDescriptor::UnixAbstractSocketConnect(
+ llvm::StringRef socket_name,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
Socket *socket = nullptr;
Status error = Socket::UnixAbstractConnect(socket_name,
m_child_processes_inherit, socket);
@@ -567,14 +625,14 @@
return eConnectionStatusSuccess;
}
-ConnectionStatus
-ConnectionFileDescriptor::SocketListenAndAccept(llvm::StringRef s,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::SocketListenAndAccept(
+ llvm::StringRef s,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
if (error_ptr)
*error_ptr = Status();
m_port_predicate.SetValue(0, eBroadcastNever);
- m_waiting_for_accept = true;
llvm::Expected<std::unique_ptr<TCPSocket>> listening_socket =
Socket::TcpListen(s, m_child_processes_inherit, &m_port_predicate);
if (!listening_socket) {
@@ -586,6 +644,8 @@
return eConnectionStatusError;
}
+ uint16_t port = listening_socket.get()->GetLocalPortNumber();
+ socket_id_callback(port != 0 ? std::to_string(port) : "");
Socket *accepted_socket;
Status error = listening_socket.get()->Accept(accepted_socket);
@@ -598,8 +658,10 @@
return eConnectionStatusSuccess;
}
-ConnectionStatus ConnectionFileDescriptor::ConnectTCP(llvm::StringRef s,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::ConnectTCP(
+ llvm::StringRef s,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
if (error_ptr)
*error_ptr = Status();
@@ -618,8 +680,10 @@
return eConnectionStatusSuccess;
}
-ConnectionStatus ConnectionFileDescriptor::ConnectUDP(llvm::StringRef s,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::ConnectUDP(
+ llvm::StringRef s,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
if (error_ptr)
*error_ptr = Status();
llvm::Expected<std::unique_ptr<UDPSocket>> socket =
@@ -637,8 +701,10 @@
return eConnectionStatusSuccess;
}
-ConnectionStatus ConnectionFileDescriptor::ConnectFD(llvm::StringRef s,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::ConnectFD(
+ llvm::StringRef s,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
#if LLDB_ENABLE_POSIX
// Just passing a native file descriptor within this current process that
// is already opened (possibly from a service or other source).
@@ -691,8 +757,10 @@
llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX");
}
-ConnectionStatus ConnectionFileDescriptor::ConnectFile(llvm::StringRef s,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::ConnectFile(
+ llvm::StringRef s,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
#if LLDB_ENABLE_POSIX
std::string addr_str = s.str();
// file:///PATH
@@ -729,16 +797,16 @@
::fcntl(fd, F_SETFL, flags);
}
}
- m_io_sp =
- std::make_shared<NativeFile>(fd, File::eOpenOptionReadWrite, true);
+ m_io_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionReadWrite, true);
return eConnectionStatusSuccess;
#endif // LLDB_ENABLE_POSIX
llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX");
}
-ConnectionStatus
-ConnectionFileDescriptor::ConnectSerialPort(llvm::StringRef s,
- Status *error_ptr) {
+ConnectionStatus ConnectionFileDescriptor::ConnectSerialPort(
+ llvm::StringRef s,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr) {
#if LLDB_ENABLE_POSIX
llvm::StringRef path, qs;
// serial:///PATH?k1=v1&k2=v2...
@@ -804,3 +872,47 @@
m_io_sp.reset(socket);
m_uri = socket->GetRemoteConnectionURI();
}
+
+llvm::Expected<std::string> lldb_private::LLGSArgToURL(llvm::StringRef url_arg,
+ bool reverse_connect) {
+ // Try parsing the argument as URL.
+ if (llvm::Optional<URI> url = URI::Parse(url_arg)) {
+ if (!reverse_connect) {
+ // Translate the scheme from LLGS notation to ConnectionFileDescriptor.
+ // If the scheme doesn't match any, pass it through to support using CFD
+ // schemes directly.
+ std::string new_scheme =
+ llvm::StringSwitch<std::string>(url->scheme)
+ .Case("tcp", "listen")
+ .Case("unix", "unix-accept")
+ .Case("unix-abstract", "unix-abstract-accept")
+ .Default(url->scheme.str());
+ return {new_scheme + url_arg.substr(url->scheme.size()).str()};
+ }
+ return {url_arg.str()};
+ }
+
+ std::string host_port = url_arg.str();
+ // If host_and_port starts with ':', default the host to be "localhost" and
+ // expect the remainder to be the port.
+ if (host_port[0] == ':')
+ host_port = std::string("localhost") + host_port;
+
+ std::string host_str;
+ std::string port_str;
+ uint16_t port;
+ // Try parsing the (preprocessed) argument as host:port pair.
+ if (!llvm::errorToBool(
+ Socket::DecodeHostAndPort(host_port, host_str, port_str, port)))
+ return {std::string(reverse_connect ? "connect://" : "listen://") +
+ host_port};
+
+ // In reverse connect mode, port must be specified.
+ if (reverse_connect)
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "port number must be specified on when using reverse connect");
+
+ // If none of the above applied, interpret the argument as UNIX socket path.
+ return {std::string("unix-accept://") + url_arg.str()};
+}
Index: lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
===================================================================
--- lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
+++ lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
@@ -38,7 +38,13 @@
bool IsConnected() const override;
- lldb::ConnectionStatus Connect(llvm::StringRef s, Status *error_ptr) override;
+ lldb::ConnectionStatus Connect(llvm::StringRef url,
+ Status *error_ptr) override;
+
+ lldb::ConnectionStatus Connect(
+ llvm::StringRef url,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
lldb::ConnectionStatus Disconnect(Status *error_ptr) override;
@@ -67,29 +73,55 @@
void CloseCommandPipe();
- lldb::ConnectionStatus SocketListenAndAccept(llvm::StringRef host_and_port,
- Status *error_ptr);
-
- lldb::ConnectionStatus ConnectTCP(llvm::StringRef host_and_port,
- Status *error_ptr);
-
- lldb::ConnectionStatus ConnectUDP(llvm::StringRef args, Status *error_ptr);
-
- lldb::ConnectionStatus NamedSocketConnect(llvm::StringRef socket_name,
- Status *error_ptr);
-
- lldb::ConnectionStatus NamedSocketAccept(llvm::StringRef socket_name,
- Status *error_ptr);
-
- lldb::ConnectionStatus UnixAbstractSocketConnect(llvm::StringRef socket_name,
- Status *error_ptr);
-
- lldb::ConnectionStatus ConnectFD(llvm::StringRef args, Status *error_ptr);
-
- lldb::ConnectionStatus ConnectFile(llvm::StringRef args, Status *error_ptr);
-
- lldb::ConnectionStatus ConnectSerialPort(llvm::StringRef args,
- Status *error_ptr);
+ lldb::ConnectionStatus SocketListenAndAccept(
+ llvm::StringRef host_and_port,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus ConnectTCP(
+ llvm::StringRef host_and_port,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus ConnectUDP(
+ llvm::StringRef args,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus NamedSocketConnect(
+ llvm::StringRef socket_name,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus NamedSocketAccept(
+ llvm::StringRef socket_name,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus UnixAbstractSocketAccept(
+ llvm::StringRef socket_name,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus UnixAbstractSocketConnect(
+ llvm::StringRef socket_name,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus ConnectFD(
+ llvm::StringRef args,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus ConnectFile(
+ llvm::StringRef args,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
+
+ lldb::ConnectionStatus ConnectSerialPort(
+ llvm::StringRef args,
+ std::function<void(llvm::StringRef local_socket_id)> socket_id_callback,
+ Status *error_ptr);
lldb::IOObjectSP m_io_sp;
@@ -103,7 +135,6 @@
std::atomic<bool> m_shutting_down; // This marks that we are shutting down so
// if we get woken up from
// BytesAvailable to disconnect, we won't try to read again.
- bool m_waiting_for_accept = false;
bool m_child_processes_inherit;
std::string m_uri;
@@ -116,6 +147,9 @@
operator=(const ConnectionFileDescriptor &) = delete;
};
+llvm::Expected<std::string> LLGSArgToURL(llvm::StringRef url_arg,
+ bool reverse_connect);
+
} // namespace lldb_private
#endif // LLDB_HOST_POSIX_CONNECTIONFILEDESCRIPTORPOSIX_H
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits