From 549718563d09e1893139af80bb85f7fb18a294b9 Mon Sep 17 00:00:00 2001 From: Oleksiy Vyalov Date: Thu, 20 Aug 2015 23:09:34 +0000 Subject: [PATCH] Make UriParser to support [$HOSTNAME] notation. http://reviews.llvm.org/D12025 llvm-svn: 245639 --- .../posix/ConnectionFileDescriptorPosix.cpp | 18 +++- .../PlatformAndroidRemoteGDBServer.cpp | 18 ++++ .../Android/PlatformAndroidRemoteGDBServer.h | 5 ++ .../gdb-server/PlatformRemoteGDBServer.cpp | 42 +++++---- .../gdb-server/PlatformRemoteGDBServer.h | 10 +++ lldb/source/Utility/UriParser.cpp | 88 ++++++++++++------- lldb/source/Utility/UriParser.h | 12 +-- lldb/unittests/Utility/UriParserTest.cpp | 24 +++++ 8 files changed, 160 insertions(+), 57 deletions(-) diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index f12f98c30b44..3e7f577458c1 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -33,6 +33,8 @@ #endif // C++ Includes +#include + // 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) { diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp index 213c3b27c6e2..f2c7af1421f2 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp @@ -16,6 +16,8 @@ #include "PlatformAndroidRemoteGDBServer.h" #include "Utility/UriParser.h" +#include + 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); +} diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h index e549435a541a..24532e6499c9 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h @@ -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); diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index b0e75d4f3457..911c946200c8 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -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(); +} diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 0bf013fdfb68..1917c2648f1d 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -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); }; diff --git a/lldb/source/Utility/UriParser.cpp b/lldb/source/Utility/UriParser.cpp index 86020d17fc3e..6febae2b17bf 100644 --- a/lldb/source/Utility/UriParser.cpp +++ b/lldb/source/Utility/UriParser.cpp @@ -10,10 +10,10 @@ #include "Utility/UriParser.h" // C Includes -#include -#include // C++ Includes +#include + // 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; } diff --git a/lldb/source/Utility/UriParser.h b/lldb/source/Utility/UriParser.h index fb129eaf79d5..8cbaaeab18cd 100644 --- a/lldb/source/Utility/UriParser.h +++ b/lldb/source/Utility/UriParser.h @@ -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_ diff --git a/lldb/unittests/Utility/UriParserTest.cpp b/lldb/unittests/Utility/UriParserTest.cpp index a11dd8e12b07..fe0a6a70f212 100644 --- a/lldb/unittests/Utility/UriParserTest.cpp +++ b/lldb/unittests/Utility/UriParserTest.cpp @@ -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");