std::string &host_str, std::string &port_str,
int32_t &port, Status *error_ptr);
+ // If this Socket is connected then return the URI used to connect.
+ virtual std::string GetRemoteConnectionURI() const { return ""; };
+
protected:
Socket(SocketProtocol protocol, bool should_close,
bool m_child_process_inherit);
bool IsValid() const override;
+ std::string GetRemoteConnectionURI() const override;
+
private:
TCPSocket(NativeSocket socket, const TCPSocket &listen_socket);
static Status Connect(llvm::StringRef name, bool child_processes_inherit,
Socket *&socket);
+ std::string GetRemoteConnectionURI() const override;
+
private:
UDPSocket(NativeSocket socket);
Status Listen(llvm::StringRef name, int backlog) override;
Status Accept(Socket *&socket) override;
+ std::string GetRemoteConnectionURI() const override;
+
protected:
DomainSocket(SocketProtocol protocol, bool child_processes_inherit);
virtual size_t GetNameOffset() const;
virtual void DeleteSocketFile(llvm::StringRef name);
+ std::string GetSocketName() const;
private:
DomainSocket(NativeSocket socket, const DomainSocket &listen_socket);
return "";
}
+std::string TCPSocket::GetRemoteConnectionURI() const {
+ if (m_socket != kInvalidSocketValue) {
+ return llvm::formatv("connect://[{0}]:{1}", GetRemoteIPAddress(),
+ GetRemotePortNumber());
+ }
+ return "";
+};
+
Status TCPSocket::CreateSocket(int domain) {
Status error;
if (IsValid())
error.Clear();
return error;
}
+
+std::string UDPSocket::GetRemoteConnectionURI() const {
+ if (m_socket != kInvalidSocketValue) {
+ return llvm::formatv("udp://[{0}]:{1}", m_sockaddr.GetIPAddress(),
+ m_sockaddr.GetPort());
+ }
+ return "";
+}
}
void ConnectionFileDescriptor::InitializeSocket(Socket *socket) {
- assert(socket->GetSocketProtocol() == Socket::ProtocolTcp);
- TCPSocket *tcp_socket = static_cast<TCPSocket *>(socket);
-
m_write_sp.reset(socket);
m_read_sp = m_write_sp;
- StreamString strm;
- strm.Printf("connect://[%s]:%u", tcp_socket->GetRemoteIPAddress().c_str(),
- tcp_socket->GetRemotePortNumber());
- m_uri = strm.GetString();
+ m_uri = socket->GetRemoteConnectionURI();
}
void DomainSocket::DeleteSocketFile(llvm::StringRef name) {
llvm::sys::fs::remove(name);
}
+
+std::string DomainSocket::GetSocketName() const {
+ if (m_socket != kInvalidSocketValue) {
+ struct sockaddr_un saddr_un;
+ saddr_un.sun_family = AF_UNIX;
+ socklen_t sock_addr_len = sizeof(struct sockaddr_un);
+ if (::getpeername(m_socket, (struct sockaddr *)&saddr_un, &sock_addr_len) ==
+ 0)
+ return std::string(saddr_un.sun_path + GetNameOffset(),
+ sock_addr_len -
+ offsetof(struct sockaddr_un, sun_path) -
+ GetNameOffset());
+ }
+ return "";
+}
+
+std::string DomainSocket::GetRemoteConnectionURI() const {
+ if (m_socket != kInvalidSocketValue) {
+ return llvm::formatv("{0}://{1}",
+ GetNameOffset() == 0 ? "unix-connect"
+ : "unix-abstract-connect",
+ GetSocketName());
+ }
+ return "";
+}
this, std::placeholders::_1),
false);
- llvm::StringRef platform_scheme;
- llvm::StringRef platform_ip;
- int platform_port;
- llvm::StringRef platform_path;
- std::string platform_uri = GetConnection()->GetURI();
- bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip,
- platform_port, platform_path);
- UNUSED_IF_ASSERT_DISABLED(ok);
- assert(ok);
-
std::ostringstream url;
// debugserver does not accept the URL scheme prefix.
#if !defined(__APPLE__)
url << m_socket_scheme << "://";
#endif
uint16_t *port_ptr = &port;
- if (m_socket_protocol == Socket::ProtocolTcp)
+ if (m_socket_protocol == Socket::ProtocolTcp) {
+ llvm::StringRef platform_scheme;
+ llvm::StringRef platform_ip;
+ int platform_port;
+ llvm::StringRef platform_path;
+ std::string platform_uri = GetConnection()->GetURI();
+ bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip,
+ platform_port, platform_path);
+ UNUSED_IF_ASSERT_DISABLED(ok);
+ assert(ok);
url << platform_ip.str() << ":" << port;
- else {
+ } else {
socket_name = GetDomainSocketPath("gdbserver").GetPath();
url << socket_name;
port_ptr = nullptr;
//===----------------------------------------------------------------------===//
#include "SocketTestUtilities.h"
+#include "lldb/Utility/UriParser.h"
#include "gtest/gtest.h"
using namespace lldb_private;
EXPECT_TRUE(socket_up->IsValid());
EXPECT_NE(socket_up->GetLocalPortNumber(), 0);
}
+
+TEST_F(SocketTest, TCPGetConnectURI) {
+ std::unique_ptr<TCPSocket> socket_a_up;
+ std::unique_ptr<TCPSocket> socket_b_up;
+ if (!IsAddressFamilySupported("127.0.0.1")) {
+ GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
+ return;
+ }
+ CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
+
+ llvm::StringRef scheme;
+ llvm::StringRef hostname;
+ int port;
+ llvm::StringRef path;
+ std::string uri(socket_a_up->GetRemoteConnectionURI());
+ EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
+ EXPECT_EQ(scheme, "connect");
+ EXPECT_EQ(port, socket_a_up->GetRemotePortNumber());
+}
+
+TEST_F(SocketTest, UDPGetConnectURI) {
+ if (!IsAddressFamilySupported("127.0.0.1")) {
+ GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support.";
+ return;
+ }
+ Socket *socket;
+ bool child_processes_inherit = false;
+ auto error =
+ UDPSocket::Connect("127.0.0.1:0", child_processes_inherit, socket);
+
+ llvm::StringRef scheme;
+ llvm::StringRef hostname;
+ int port;
+ llvm::StringRef path;
+ std::string uri(socket->GetRemoteConnectionURI());
+ EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
+ EXPECT_EQ(scheme, "udp");
+}
+
+#ifndef LLDB_DISABLE_POSIX
+TEST_F(SocketTest, DomainGetConnectURI) {
+ llvm::SmallString<64> domain_path;
+ std::error_code EC =
+ llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path);
+ ASSERT_FALSE(EC);
+ llvm::sys::path::append(domain_path, "test");
+
+ std::unique_ptr<DomainSocket> socket_a_up;
+ std::unique_ptr<DomainSocket> socket_b_up;
+ CreateDomainConnectedSockets(domain_path, &socket_a_up, &socket_b_up);
+
+ llvm::StringRef scheme;
+ llvm::StringRef hostname;
+ int port;
+ llvm::StringRef path;
+ std::string uri(socket_a_up->GetRemoteConnectionURI());
+ EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path));
+ EXPECT_EQ(scheme, "unix-connect");
+ EXPECT_EQ(path, domain_path);
+}
+#endif
\ No newline at end of file