Provide ADB port forwarding support for abstract sockets.

http://reviews.llvm.org/D14262

llvm-svn: 251879
This commit is contained in:
Oleksiy Vyalov 2015-11-03 01:37:01 +00:00
parent 52151b3edf
commit e7df5f5d41
6 changed files with 102 additions and 29 deletions

View File

@ -34,6 +34,17 @@ class SocketAddress;
class ConnectionFileDescriptor : public Connection
{
public:
static const char* LISTEN_SCHEME;
static const char* ACCEPT_SCHEME;
static const char* UNIX_ACCEPT_SCHEME;
static const char* CONNECT_SCHEME;
static const char* TCP_CONNECT_SCHEME;
static const char* UDP_SCHEME;
static const char* UNIX_CONNECT_SCHEME;
static const char* UNIX_ABSTRACT_CONNECT_SCHEME;
static const char* FD_SCHEME;
static const char* FILE_SCHEME;
ConnectionFileDescriptor(bool child_processes_inherit = false);
ConnectionFileDescriptor(int fd, bool owns_fd);

View File

@ -53,6 +53,31 @@
using namespace lldb;
using namespace lldb_private;
const char* ConnectionFileDescriptor::LISTEN_SCHEME = "listen";
const char* ConnectionFileDescriptor::ACCEPT_SCHEME = "accept";
const char* ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept";
const char* ConnectionFileDescriptor::CONNECT_SCHEME = "connect";
const char* ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect";
const char* ConnectionFileDescriptor::UDP_SCHEME = "udp";
const char* ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect";
const char* ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = "unix-abstract-connect";
const char* ConnectionFileDescriptor::FD_SCHEME = "fd";
const char* ConnectionFileDescriptor::FILE_SCHEME = "file";
namespace {
const char*
GetURLAddress(const char *url, const char *scheme)
{
const auto prefix = std::string(scheme) + "://";
if (strstr(url, prefix.c_str()) != url)
return nullptr;
return url + prefix.size();
}
}
ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit)
: Connection()
, m_pipe()
@ -154,51 +179,51 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
if (s && s[0])
{
if (strstr(s, "listen://") == s)
const char *addr = nullptr;
if ((addr = GetURLAddress(s, LISTEN_SCHEME)))
{
// listen://HOST:PORT
return SocketListenAndAccept(s + strlen("listen://"), error_ptr);
return SocketListenAndAccept(addr, error_ptr);
}
else if (strstr(s, "accept://") == s)
else if ((addr = GetURLAddress(s, ACCEPT_SCHEME)))
{
// unix://SOCKNAME
return NamedSocketAccept(s + strlen("accept://"), error_ptr);
return NamedSocketAccept(addr, error_ptr);
}
else if (strstr(s, "unix-accept://") == s)
else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME)))
{
// unix://SOCKNAME
return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr);
return NamedSocketAccept(addr, error_ptr);
}
else if (strstr(s, "connect://") == s)
else if ((addr = GetURLAddress(s, CONNECT_SCHEME)))
{
return ConnectTCP(s + strlen("connect://"), error_ptr);
return ConnectTCP(addr, error_ptr);
}
else if (strstr(s, "tcp-connect://") == s)
else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME)))
{
return ConnectTCP(s + strlen("tcp-connect://"), error_ptr);
return ConnectTCP(addr, error_ptr);
}
else if (strstr(s, "udp://") == s)
else if ((addr = GetURLAddress(s, UDP_SCHEME)))
{
return ConnectUDP(s + strlen("udp://"), error_ptr);
return ConnectUDP(addr, error_ptr);
}
else if (strstr(s, "unix-connect://") == s)
else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME)))
{
// unix-connect://SOCKNAME
return NamedSocketConnect(s + strlen("unix-connect://"), error_ptr);
return NamedSocketConnect(addr, error_ptr);
}
else if (strstr(s, "unix-abstract-connect://") == s)
else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME)))
{
// unix-abstract-connect://SOCKNAME
return UnixAbstractSocketConnect(s + strlen("unix-abstract-connect://"), error_ptr);
return UnixAbstractSocketConnect(addr, error_ptr);
}
#ifndef LLDB_DISABLE_POSIX
else if (strstr(s, "fd://") == s)
else if ((addr = GetURLAddress(s, FD_SCHEME)))
{
// Just passing a native file descriptor within this current process
// that is already opened (possibly from a service or other source).
s += strlen("fd://");
bool success = false;
int fd = StringConvert::ToSInt32(s, -1, 0, &success);
int fd = StringConvert::ToSInt32(addr, -1, 0, &success);
if (success)
{
@ -244,21 +269,21 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
m_read_sp.reset(new File(fd, false));
m_write_sp.reset(new File(fd, false));
}
m_uri.assign(s);
m_uri.assign(addr);
return eConnectionStatusSuccess;
}
}
if (error_ptr)
error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"fd://%s\"", s);
error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", s);
m_read_sp.reset();
m_write_sp.reset();
return eConnectionStatusError;
}
else if (strstr(s, "file://") == s)
else if ((addr = GetURLAddress(s, FILE_SCHEME)))
{
// file:///PATH
const char *path = s + strlen("file://");
const char *path = addr;
int fd = -1;
do
{

View File

@ -50,6 +50,9 @@ const size_t kMaxPushData = 2*1024;
// Default mode for pushed files.
const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
const char * kSocketNamespaceAbstract = "localabstract";
const char * kSocketNamespaceFileSystem = "localfilesystem";
} // namespace
Error
@ -145,10 +148,17 @@ AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_p
}
Error
AdbClient::SetPortForwarding (const uint16_t local_port, const char* remote_socket_name)
AdbClient::SetPortForwarding (const uint16_t local_port,
const char* remote_socket_name,
const UnixSocketNamespace socket_namespace)
{
char message[PATH_MAX];
snprintf (message, sizeof (message), "forward:tcp:%d;localfilesystem:%s", local_port, remote_socket_name);
const char * sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) ?
kSocketNamespaceAbstract : kSocketNamespaceFileSystem;
snprintf (message, sizeof (message), "forward:tcp:%d;%s:%s",
local_port,
sock_namespace_str,
remote_socket_name);
const auto error = SendDeviceMessage (message);
if (error.Fail ())

View File

@ -33,6 +33,12 @@ namespace platform_android {
class AdbClient
{
public:
enum UnixSocketNamespace
{
UnixSocketNamespaceAbstract,
UnixSocketNamespaceFileSystem,
};
using DeviceIDList = std::list<std::string>;
static Error
@ -51,7 +57,9 @@ public:
SetPortForwarding (const uint16_t local_port, const uint16_t remote_port);
Error
SetPortForwarding (const uint16_t local_port, const char* remote_socket_name);
SetPortForwarding (const uint16_t local_port,
const char* remote_socket_name,
const UnixSocketNamespace socket_namespace);
Error
DeletePortForwarding (const uint16_t local_port);

View File

@ -11,7 +11,6 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Host/common/TCPSocket.h"
#include "AdbClient.h"
#include "PlatformAndroidRemoteGDBServer.h"
#include "Utility/UriParser.h"
@ -27,6 +26,7 @@ static Error
ForwardPortWithAdb (const uint16_t local_port,
const uint16_t remote_port,
const char* remote_socket_name,
const llvm::Optional<AdbClient::UnixSocketNamespace>& socket_namespace,
std::string& device_id)
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
@ -49,7 +49,11 @@ ForwardPortWithAdb (const uint16_t local_port,
if (log)
log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", remote_socket_name, local_port);
return adb.SetPortForwarding(local_port, remote_socket_name);
if (!socket_namespace)
return Error("Invalid socket namespace");
return adb.SetPortForwarding(local_port, remote_socket_name, *socket_namespace);
}
static Error
@ -129,6 +133,12 @@ PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args)
if (host != "localhost")
m_device_id = host;
m_socket_namespace.reset();
if (scheme == ConnectionFileDescriptor::UNIX_CONNECT_SCHEME)
m_socket_namespace = AdbClient::UnixSocketNamespaceFileSystem;
else if (scheme == ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME)
m_socket_namespace = AdbClient::UnixSocketNamespaceAbstract;
std::string connect_url;
auto error = MakeConnectURL (g_remote_platform_pid,
(remote_port < 0) ? 0 : remote_port,
@ -196,7 +206,11 @@ PlatformAndroidRemoteGDBServer::MakeConnectURL(const lldb::pid_t pid,
if (error.Fail())
return error;
error = ForwardPortWithAdb(local_port, remote_port, remote_socket_name, m_device_id);
error = ForwardPortWithAdb(local_port,
remote_port,
remote_socket_name,
m_socket_namespace,
m_device_id);
if (error.Success())
{
m_port_forwards[pid] = local_port;

View File

@ -19,6 +19,10 @@
// Project includes
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
#include "llvm/ADT/Optional.h"
#include "AdbClient.h"
namespace lldb_private {
namespace platform_android {
@ -38,6 +42,7 @@ public:
protected:
std::string m_device_id;
std::map<lldb::pid_t, uint16_t> m_port_forwards;
llvm::Optional<AdbClient::UnixSocketNamespace> m_socket_namespace;
bool
LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) override;