[lldb-dap] Make connection URLs match lldb (#144770)

Use the same scheme as ConnectionFileDescriptor::Connect and use
"listen" and "accept". Addresses feedback from a Pavel in a different PR
[1].

[1] https://github.com/llvm/llvm-project/pull/143628#discussion_r2152225200
This commit is contained in:
Jonas Devlieghere 2025-06-19 20:48:07 -05:00 committed by GitHub
parent 513bcf6d01
commit 4f991cc995
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 63 additions and 19 deletions

View File

@ -74,6 +74,11 @@ public:
ProtocolUnixAbstract
};
enum SocketMode {
ModeAccept,
ModeConnect,
};
struct HostAndPort {
std::string hostname;
uint16_t port;
@ -83,6 +88,10 @@ public:
}
};
using ProtocolModePair = std::pair<SocketProtocol, SocketMode>;
static std::optional<ProtocolModePair>
GetProtocolAndMode(llvm::StringRef scheme);
static const NativeSocket kInvalidSocketValue;
~Socket() override;

View File

@ -271,7 +271,8 @@ Socket::UdpConnect(llvm::StringRef host_and_port) {
return UDPSocket::CreateConnected(host_and_port);
}
llvm::Expected<Socket::HostAndPort> Socket::DecodeHostAndPort(llvm::StringRef host_and_port) {
llvm::Expected<Socket::HostAndPort>
Socket::DecodeHostAndPort(llvm::StringRef host_and_port) {
static llvm::Regex g_regex("([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)");
HostAndPort ret;
llvm::SmallVector<llvm::StringRef, 3> matches;
@ -347,8 +348,8 @@ Status Socket::Write(const void *buf, size_t &num_bytes) {
", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64
" (error = %s)",
static_cast<void *>(this), static_cast<uint64_t>(m_socket), buf,
static_cast<uint64_t>(src_len),
static_cast<int64_t>(bytes_sent), error.AsCString());
static_cast<uint64_t>(src_len), static_cast<int64_t>(bytes_sent),
error.AsCString());
}
return error;
@ -476,3 +477,28 @@ llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &OS,
const Socket::HostAndPort &HP) {
return OS << '[' << HP.hostname << ']' << ':' << HP.port;
}
std::optional<Socket::ProtocolModePair>
Socket::GetProtocolAndMode(llvm::StringRef scheme) {
// Keep in sync with ConnectionFileDescriptor::Connect.
return llvm::StringSwitch<std::optional<ProtocolModePair>>(scheme)
.Case("listen", ProtocolModePair{SocketProtocol::ProtocolTcp,
SocketMode::ModeAccept})
.Cases("accept", "unix-accept",
ProtocolModePair{SocketProtocol::ProtocolUnixDomain,
SocketMode::ModeAccept})
.Case("unix-abstract-accept",
ProtocolModePair{SocketProtocol::ProtocolUnixAbstract,
SocketMode::ModeAccept})
.Cases("connect", "tcp-connect",
ProtocolModePair{SocketProtocol::ProtocolTcp,
SocketMode::ModeConnect})
.Case("udp", ProtocolModePair{SocketProtocol::ProtocolTcp,
SocketMode::ModeConnect})
.Case("unix-connect", ProtocolModePair{SocketProtocol::ProtocolUnixDomain,
SocketMode::ModeConnect})
.Case("unix-abstract-connect",
ProtocolModePair{SocketProtocol::ProtocolUnixAbstract,
SocketMode::ModeConnect})
.Default(std::nullopt);
}

View File

@ -54,7 +54,7 @@ class TestDAP_server(lldbdap_testcase.DAPTestCaseBase):
Test launching a binary with a lldb-dap in server mode on a specific port.
"""
self.build()
(_, connection) = self.start_server(connection="tcp://localhost:0")
(_, connection) = self.start_server(connection="listen://localhost:0")
self.run_debug_session(connection, "Alice")
self.run_debug_session(connection, "Bob")
@ -72,7 +72,7 @@ class TestDAP_server(lldbdap_testcase.DAPTestCaseBase):
self.addTearDownHook(cleanup)
self.build()
(_, connection) = self.start_server(connection="unix://" + name)
(_, connection) = self.start_server(connection="accept://" + name)
self.run_debug_session(connection, "Alice")
self.run_debug_session(connection, "Bob")
@ -82,7 +82,7 @@ class TestDAP_server(lldbdap_testcase.DAPTestCaseBase):
Test launching a binary with lldb-dap in server mode and shutting down the server while the debug session is still active.
"""
self.build()
(process, connection) = self.start_server(connection="tcp://localhost:0")
(process, connection) = self.start_server(connection="listen://localhost:0")
self.dap_server = dap_server.DebugAdapterServer(
connection=connection,
)

View File

@ -28,8 +28,8 @@ def connection
MetaVarName<"<connection>">,
HelpText<
"Communicate with the lldb-dap tool over the specified connection. "
"Connections are specified like 'tcp://[host]:port' or "
"'unix:///path'.">;
"Connections are specified like 'listen://[host]:port' or "
"'accept:///path'.">;
def launch_target: S<"launch-target">,
MetaVarName<"<target>">,

View File

@ -26,7 +26,7 @@ export class LLDBDapServer implements vscode.Disposable {
args: string[],
options?: child_process.SpawnOptionsWithoutStdio,
): Promise<{ host: string; port: number } | undefined> {
const dapArgs = [...args, "--connection", "connect://localhost:0"];
const dapArgs = [...args, "--connection", "listen://localhost:0" ];
if (!(await this.shouldContinueStartup(dapPath, dapArgs))) {
return undefined;
}

View File

@ -127,7 +127,7 @@ EXAMPLES:
parent over stdio. Passing a --connection URI will cause lldb-dap to listen
for a connection in the specified mode.
lldb-dap --connection connection://localhost:<port>
lldb-dap --connection listen://localhost:<port>
Passing --wait-for-debugger will pause the process at startup and wait for a
debugger to attach to the process.
@ -226,23 +226,32 @@ static llvm::Expected<std::pair<Socket::SocketProtocol, std::string>>
validateConnection(llvm::StringRef conn) {
auto uri = lldb_private::URI::Parse(conn);
if (uri && (uri->scheme == "tcp" || uri->scheme == "connect" ||
!uri->hostname.empty() || uri->port)) {
auto make_error = [conn]() -> llvm::Error {
return llvm::createStringError(
"Unsupported connection specifier, expected 'accept:///path' or "
"'listen://[host]:port', got '%s'.",
conn.str().c_str());
};
if (!uri)
return make_error();
std::optional<Socket::ProtocolModePair> protocol_and_mode =
Socket::GetProtocolAndMode(uri->scheme);
if (!protocol_and_mode || protocol_and_mode->second != Socket::ModeAccept)
return make_error();
if (protocol_and_mode->first == Socket::ProtocolTcp) {
return std::make_pair(
Socket::ProtocolTcp,
formatv("[{0}]:{1}", uri->hostname.empty() ? "0.0.0.0" : uri->hostname,
uri->port.value_or(0)));
}
if (uri && (uri->scheme == "unix" || uri->scheme == "unix-connect" ||
uri->path != "/")) {
if (protocol_and_mode->first == Socket::ProtocolUnixDomain)
return std::make_pair(Socket::ProtocolUnixDomain, uri->path.str());
}
return llvm::createStringError(
"Unsupported connection specifier, expected 'unix-connect:///path' or "
"'connect://[host]:port', got '%s'.",
conn.str().c_str());
return make_error();
}
static llvm::Error