Make UriParser to support [$HOSTNAME] notation.

http://reviews.llvm.org/D12025

llvm-svn: 245639
This commit is contained in:
Oleksiy Vyalov
2015-08-20 23:09:34 +00:00
parent 2df38cd0c4
commit 549718563d
8 changed files with 160 additions and 57 deletions

View File

@@ -33,6 +33,8 @@
#endif
// C++ Includes
#include <sstream>
// Other libraries and framework includes
#include "llvm/Support/ErrorHandling.h"
#if defined(__APPLE__)
@@ -47,6 +49,8 @@
#include "lldb/Host/Socket.h"
#include "lldb/Interpreter/Args.h"
#include "Utility/UriParser.h"
using namespace lldb;
using namespace lldb_private;
@@ -169,10 +173,16 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
else if (strstr(s, "adb://") == s)
{
int port = -1;
sscanf(s, "adb://%*[^:]:%d", &port);
char host_and_port[sizeof("localhost:65535")];
snprintf(host_and_port, sizeof(host_and_port), "localhost:%d", port);
return ConnectTCP(host_and_port, error_ptr);
std::string scheme, host, path;
if (!UriParser::Parse(s, scheme, host, port, path))
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat("Failed to parse URL '%s'", s);
return eConnectionStatusError;
}
std::ostringstream host_and_port;
host_and_port << "localhost:" << port;
return ConnectTCP(host_and_port.str().c_str(), error_ptr);
}
else if (strstr(s, "connect://") == s)
{

View File

@@ -16,6 +16,8 @@
#include "PlatformAndroidRemoteGDBServer.h"
#include "Utility/UriParser.h"
#include <sstream>
using namespace lldb;
using namespace lldb_private;
using namespace platform_android;
@@ -135,3 +137,19 @@ PlatformAndroidRemoteGDBServer::DeleteForwardPort (lldb::pid_t pid)
}
m_port_forwards.erase(it);
}
std::string
PlatformAndroidRemoteGDBServer::MakeServerUrl(const char* scheme,
const char* hostname,
uint16_t port)
{
std::ostringstream hostname_str;
if (!strcmp(scheme, "adb"))
hostname_str << "[" << hostname << "]";
else
hostname_str << hostname;
return PlatformRemoteGDBServer::MakeServerUrl(scheme,
hostname_str.str().c_str(),
port);
}

View File

@@ -49,6 +49,11 @@ protected:
void
DeleteForwardPort (lldb::pid_t pid);
std::string
MakeServerUrl(const char* scheme,
const char* hostname,
uint16_t port) override;
private:
DISALLOW_COPY_AND_ASSIGN (PlatformAndroidRemoteGDBServer);

View File

@@ -40,23 +40,6 @@ using namespace lldb_private::platform_gdb_server;
static bool g_initialized = false;
static std::string MakeGdbServerUrl(
const std::string &platform_scheme,
const std::string &platform_hostname,
uint16_t port)
{
const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
StreamString result;
result.Printf("%s://%s:%u",
override_scheme ? override_scheme : platform_scheme.c_str(),
override_hostname ? override_hostname : platform_hostname.c_str(),
port + port_offset);
return result.GetString();
}
void
PlatformRemoteGDBServer::Initialize ()
{
@@ -969,3 +952,28 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()
return m_remote_signals_sp;
}
std::string
PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme,
const std::string &platform_hostname,
uint16_t port)
{
const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
return MakeServerUrl(override_scheme ? override_scheme : platform_scheme.c_str(),
override_hostname ? override_hostname : platform_hostname.c_str(),
port + port_offset);
}
std::string
PlatformRemoteGDBServer::MakeServerUrl(const char* scheme,
const char* hostname,
uint16_t port)
{
StreamString result;
result.Printf("%s://%s:%u", scheme, hostname, port);
return result.GetString();
}

View File

@@ -234,7 +234,17 @@ protected:
virtual bool
KillSpawnedProcess (lldb::pid_t pid);
virtual std::string
MakeServerUrl(const char* scheme,
const char* hostname,
uint16_t port);
private:
std::string
MakeGdbServerUrl(const std::string &platform_scheme,
const std::string &platform_hostname,
uint16_t port);
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);
};

View File

@@ -10,10 +10,10 @@
#include "Utility/UriParser.h"
// C Includes
#include <stdlib.h>
#include <stdio.h>
// C++ Includes
#include <cstring>
// Other libraries and framework includes
// Project includes
#include "lldb/Host/StringConvert.h"
@@ -24,43 +24,71 @@ using namespace lldb_private;
// UriParser::Parse
//----------------------------------------------------------------------
bool
UriParser::Parse(const char* uri,
std::string& scheme,
std::string& hostname,
int& port,
std::string& path
)
UriParser::Parse(const std::string& uri,
std::string& scheme,
std::string& hostname,
int& port,
std::string& path)
{
char scheme_buf[100] = {0};
char hostname_buf[256] = {0};
char port_buf[11] = {0}; // 10==strlen(2^32)
char path_buf[2049] = {'/', 0};
bool ok = false;
if (4==sscanf(uri, "%99[^:/]://%255[^/:]:%10[^/]/%2047s", scheme_buf, hostname_buf, port_buf, path_buf+1)) { ok = true; }
else if (3==sscanf(uri, "%99[^:/]://%255[^/:]:%10[^/]", scheme_buf, hostname_buf, port_buf)) { ok = true; }
else if (3==sscanf(uri, "%99[^:/]://%255[^/]/%2047s", scheme_buf, hostname_buf, path_buf+1)) { ok = true; }
else if (2==sscanf(uri, "%99[^:/]://%255[^/]", scheme_buf, hostname_buf)) { ok = true; }
std::string tmp_scheme, tmp_hostname, tmp_port, tmp_path;
bool success = false;
int port_tmp = -1;
if (port_buf[0])
static const char* kSchemeSep = "://";
auto pos = uri.find(kSchemeSep);
if (pos == std::string::npos)
return false;
// Extract path.
tmp_scheme = uri.substr(0, pos);
auto host_pos = pos + strlen(kSchemeSep);
auto path_pos = uri.find_first_of("/", host_pos);
if (path_pos != std::string::npos)
tmp_path = uri.substr(path_pos);
else
tmp_path = "/";
auto host_port = uri.substr(
host_pos, ((path_pos != std::string::npos) ? path_pos : uri.size()) - host_pos);
// Extract hostname
if (host_port[0] == '[')
{
port_tmp = StringConvert::ToUInt32(port_buf, UINT32_MAX, 10, &success);
// hostname is enclosed with square brackets.
pos = host_port.find(']');
if (pos == std::string::npos)
return false;
tmp_hostname = host_port.substr(1, pos - 1);
host_port.erase(0, pos + 1);
}
else
{
pos = host_port.find(':');
tmp_hostname = host_port.substr(0, (pos != std::string::npos) ? pos : host_port.size());
host_port.erase(0, (pos != std::string::npos) ? pos : host_port.size());
}
// Extract port
tmp_port = host_port;
if (!tmp_port.empty())
{
if (tmp_port[0] != ':')
return false;
tmp_port = tmp_port.substr(1);
bool success = false;
auto port_tmp = StringConvert::ToUInt32(tmp_port.c_str(), UINT32_MAX, 10, &success);
if (!success || port_tmp > 65535)
{
// there are invalid characters in port_buf
return false;
}
}
if (ok)
{
scheme.assign(scheme_buf);
hostname.assign(hostname_buf);
port = port_tmp;
path.assign(path_buf);
}
return ok;
else
port = -1;
scheme = tmp_scheme;
hostname = tmp_hostname;
path = tmp_path;
return true;
}

View File

@@ -28,12 +28,12 @@ public:
//
// if the url is invalid, function returns false and
// output parameters remain unchanged
static bool Parse(const char* uri,
std::string& scheme,
std::string& hostname,
int& port,
std::string& path
);
static bool
Parse(const std::string& uri,
std::string& scheme,
std::string& hostname,
int& port,
std::string& path);
};
#endif // utility_UriParser_h_

View File

@@ -79,12 +79,36 @@ TEST_F (UriParserTest, MinimalPortPath)
VALIDATE
}
TEST_F (UriParserTest, LongPath)
{
const UriTestCase testCase("x://y/abc/def/xyz", "x", "y", -1, "/abc/def/xyz");
VALIDATE
}
TEST_F (UriParserTest, TypicalPortPath)
{
const UriTestCase testCase("connect://192.168.100.132:5432/", "connect", "192.168.100.132", 5432, "/");
VALIDATE
}
TEST_F (UriParserTest, BracketedHostnamePort)
{
const UriTestCase testCase("connect://[192.168.100.132]:5432/", "connect", "192.168.100.132", 5432, "/");
VALIDATE
}
TEST_F (UriParserTest, BracketedHostname)
{
const UriTestCase testCase("connect://[192.168.100.132]", "connect", "192.168.100.132", -1, "/");
VALIDATE
}
TEST_F (UriParserTest, BracketedHostnameWithColon)
{
const UriTestCase testCase("connect://[192.168.100.132:5555]:1234", "connect", "192.168.100.132:5555", 1234, "/");
VALIDATE
}
TEST_F (UriParserTest, SchemeHostSeparator)
{
const UriTestCase testCase("x:/y");