Hi clayborg, ovyalov, sivachandra,
Why did I make this patch?
I am trying to get the remote tests running linux->linux when the hosts are
multi-homed, localhost or don't have proper DNS entries.
I need to add Socket::Get[Remote/Local]IpAddress
I wanted to make some unit tests to test it
So I created a unit test binary
Socket has a really, really big number of dependencies (like all of lldb)
I removed references to Args::StringToUInt32 and created SocketGlue to get the
unit test binary linking without pulling in everything
It's a bit of a hack but it gets the job done
I needed to use inet_ntop, which doesn't exist on Windows XP, so I implemented
that, too
REPOSITORY
rL LLVM
http://reviews.llvm.org/D6917
Files:
gtest/gtest.xcodeproj/project.pbxproj
include/lldb/Host/Socket.h
include/lldb/Host/SocketAddress.h
lldb.xcodeproj/project.pbxproj
source/Host/common/Socket.cpp
source/Host/common/SocketAddress.cpp
source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: gtest/gtest.xcodeproj/project.pbxproj
===================================================================
--- gtest/gtest.xcodeproj/project.pbxproj
+++ gtest/gtest.xcodeproj/project.pbxproj
@@ -12,14 +12,19 @@
236ED33619D490B0008CA7D7 /* Makefile.rules */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.rules; sourceTree = "<group>"; };
33064C981A5C7A1A0033D415 /* UriParserTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParserTest.cpp; path = Utility/UriParserTest.cpp; sourceTree = "<group>"; };
33064C9D1A5C7AC90033D415 /* do-gtest.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = "do-gtest.py"; sourceTree = "<group>"; };
+ 330E475C1A609CF600FD2884 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Host/Makefile; sourceTree = "<group>"; };
+ 330E475D1A609CF600FD2884 /* SocketTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SocketTest.cpp; path = Host/SocketTest.cpp; sourceTree = "<group>"; };
+ 330E475E1A60B31F00FD2884 /* SocketTestGlue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SocketTestGlue.cpp; path = Host/SocketTestGlue.cpp; sourceTree = "<group>"; };
+ 330E47621A62451800FD2884 /* SocketAddressTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SocketAddressTest.cpp; path = Host/SocketAddressTest.cpp; sourceTree = "<group>"; };
338C47F41A1E67B900B46077 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Utility/Makefile; sourceTree = "<group>"; };
338C47F51A1E67B900B46077 /* StringExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractorTest.cpp; path = Utility/StringExtractorTest.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXGroup section */
236ED32F19D4901D008CA7D7 /* unittest */ = {
isa = PBXGroup;
children = (
+ 330E475B1A609CDF00FD2884 /* Host */,
338C47F31A1E677900B46077 /* Utility */,
236ED33019D4903E008CA7D7 /* Plugins */,
);
@@ -68,6 +73,17 @@
);
sourceTree = "<group>";
};
+ 330E475B1A609CDF00FD2884 /* Host */ = {
+ isa = PBXGroup;
+ children = (
+ 330E475E1A60B31F00FD2884 /* SocketTestGlue.cpp */,
+ 330E475C1A609CF600FD2884 /* Makefile */,
+ 330E475D1A609CF600FD2884 /* SocketTest.cpp */,
+ 330E47621A62451800FD2884 /* SocketAddressTest.cpp */,
+ );
+ name = Host;
+ sourceTree = "<group>";
+ };
338C47F31A1E677900B46077 /* Utility */ = {
isa = PBXGroup;
children = (
Index: include/lldb/Host/Socket.h
===================================================================
--- include/lldb/Host/Socket.h
+++ include/lldb/Host/Socket.h
@@ -70,30 +70,43 @@
int GetOption (int level, int option_name, int &option_value);
int SetOption (int level, int option_name, int option_value);
- static uint16_t GetPortNumber(const NativeSocket& socket);
- uint16_t GetPortNumber () const;
+ // returns port number or 0 if error
+ static uint16_t GetLocalPortNumber (const NativeSocket& socket);
+
+ // returns port number or 0 if error
+ uint16_t GetLocalPortNumber () const;
+
+ // returns ip address string or empty string if error
+ std::string GetLocalIPAddress () const;
+
+ // must be connected
+ // returns port number or 0 if error
+ uint16_t GetRemotePortNumber () const;
+
+ // must be connected
+ // returns ip address string or empty string if error
+ std::string GetRemoteIPAddress () const;
NativeSocket GetNativeSocket () const { return m_socket; }
- SocketProtocol GetSocketProtocol() const { return m_protocol; }
+ SocketProtocol GetSocketProtocol () const { return m_protocol; }
virtual Error Read (void *buf, size_t &num_bytes);
virtual Error Write (const void *buf, size_t &num_bytes);
- virtual Error PreDisconnect();
- virtual Error Close();
+ virtual Error PreDisconnect ();
+ virtual Error Close ();
- virtual bool IsValid() const { return m_socket != kInvalidSocketValue; }
- virtual WaitableHandle GetWaitableHandle();
+ virtual bool IsValid () const { return m_socket != kInvalidSocketValue; }
+ virtual WaitableHandle GetWaitableHandle ();
-protected:
static bool
DecodeHostAndPort (llvm::StringRef host_and_port,
std::string &host_str,
std::string &port_str,
int32_t& port,
Error *error_ptr);
-
+protected:
SocketProtocol m_protocol;
NativeSocket m_socket;
SocketAddress m_udp_send_sockaddr; // Send address used for UDP connections.
Index: include/lldb/Host/SocketAddress.h
===================================================================
--- include/lldb/Host/SocketAddress.h
+++ include/lldb/Host/SocketAddress.h
@@ -31,6 +31,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include <string>
namespace lldb_private {
@@ -100,6 +101,12 @@
SetFamily (sa_family_t family);
//------------------------------------------------------------------
+ // Get the address
+ //------------------------------------------------------------------
+ std::string
+ GetIPAddress () const;
+
+ //------------------------------------------------------------------
// Get the port if the socket address for the family has a port
//------------------------------------------------------------------
uint16_t
Index: lldb.xcodeproj/project.pbxproj
===================================================================
--- lldb.xcodeproj/project.pbxproj
+++ lldb.xcodeproj/project.pbxproj
@@ -583,6 +583,8 @@
26FFC19E14FC072100087D58 /* DynamicLoaderPOSIXDYLD.h in Headers */ = {isa = PBXBuildFile; fileRef = 26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */; };
33064C9A1A5C7A330033D415 /* UriParser.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 33064C991A5C7A330033D415 /* UriParser.cpp */; };
33064C9C1A5C7A490033D415 /* UriParser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 33064C9B1A5C7A490033D415 /* UriParser.h */; };
+ 330E475F1A60B84400FD2884 /* ConnectionFileDescriptorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */; };
+ 330E47611A60B91000FD2884 /* ConnectionFileDescriptorPosix.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 330E47601A60B91000FD2884 /* ConnectionFileDescriptorPosix.h */; };
3FDFDDBD199C3A06009756A7 /* FileAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */; };
3FDFDDBF199D345E009756A7 /* FileCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBE199D345E009756A7 /* FileCache.cpp */; };
3FDFDDC6199D37ED009756A7 /* FileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */; };
@@ -937,6 +939,7 @@
AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */,
33064C9C1A5C7A490033D415 /* UriParser.h in CopyFiles */,
33064C9A1A5C7A330033D415 /* UriParser.cpp in CopyFiles */,
+ 330E47611A60B91000FD2884 /* ConnectionFileDescriptorPosix.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@@ -1801,6 +1804,7 @@
26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderPOSIXDYLD.h; sourceTree = "<group>"; };
33064C991A5C7A330033D415 /* UriParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParser.cpp; path = source/Utility/UriParser.cpp; sourceTree = "<group>"; };
33064C9B1A5C7A490033D415 /* UriParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UriParser.h; path = source/Utility/UriParser.h; sourceTree = "<group>"; };
+ 330E47601A60B91000FD2884 /* ConnectionFileDescriptorPosix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionFileDescriptorPosix.h; path = include/lldb/Host/posix/ConnectionFileDescriptorPosix.h; sourceTree = SOURCE_ROOT; };
3F5E8AF31A40D4A500A73232 /* PipeBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PipeBase.h; path = include/lldb/Host/PipeBase.h; sourceTree = "<group>"; };
3FDFD6C3199C396E009756A7 /* FileAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileAction.h; path = include/lldb/Target/FileAction.h; sourceTree = "<group>"; };
3FDFDDBC199C3A06009756A7 /* FileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileAction.cpp; path = source/Target/FileAction.cpp; sourceTree = "<group>"; };
@@ -4172,6 +4176,7 @@
3FDFDDC4199D37BE009756A7 /* posix */ = {
isa = PBXGroup;
children = (
+ 330E47601A60B91000FD2884 /* ConnectionFileDescriptorPosix.h */,
AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */,
3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */,
3FDFE53019A292F0009756A7 /* HostInfoPosix.cpp */,
@@ -5027,6 +5032,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 330E475F1A60B84400FD2884 /* ConnectionFileDescriptorPosix.cpp in Sources */,
26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Index: source/Host/common/Socket.cpp
===================================================================
--- source/Host/common/Socket.cpp
+++ source/Host/common/Socket.cpp
@@ -16,7 +16,6 @@
#include "lldb/Host/Host.h"
#include "lldb/Host/SocketAddress.h"
#include "lldb/Host/TimeValue.h"
-#include "lldb/Interpreter/Args.h"
#ifdef __ANDROID_NDK__
#include <linux/tcp.h>
@@ -222,17 +221,17 @@
// as port zero is a special code for "find an open port
// for me".
if (port == 0)
- port = listen_socket->GetPortNumber();
+ port = listen_socket->GetLocalPortNumber ();
// Set the port predicate since when doing a listen://<host>:<port>
// it often needs to accept the incoming connection which is a blocking
// system call. Allowing access to the bound port using a predicate allows
// us to wait for the port predicate to be set to a non-zero value from
// another thread in an efficient manor.
if (predicate)
- predicate->SetValue(port, eBroadcastAlways);
+ predicate->SetValue (port, eBroadcastAlways);
- socket = listen_socket.release();
+ socket = listen_socket.release ();
}
return error;
@@ -533,27 +532,33 @@
if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) &&
regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str))
{
- port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
- if (port != INT32_MIN)
+ port = ::strtoul (port_str.c_str(), nullptr, 10);
+ if (port < 65536)
{
if (error_ptr)
error_ptr->Clear();
return true;
}
+ // port is too large
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data());
+ return false;
}
}
-
+
// If this was unsuccessful, then check if it's simply a signed 32-bit integer, representing
// a port with an empty host.
host_str.clear();
port_str.clear();
- port = Args::StringToSInt32(host_and_port.data(), INT32_MIN);
- if (port != INT32_MIN)
+ port = ::strtoul (host_and_port.data(), nullptr, 10);
+ if (port < 65536)
{
port_str = host_and_port;
+ if (error_ptr)
+ error_ptr->Clear();
return true;
}
-
+
if (error_ptr)
error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data());
return false;
@@ -688,7 +693,7 @@
return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value));
}
-uint16_t Socket::GetPortNumber(const NativeSocket& socket)
+uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket)
{
// We bound to port zero, so we need to figure out which port we actually bound to
if (socket >= 0)
@@ -702,7 +707,46 @@
}
// Return the port number that is being used by the socket.
-uint16_t Socket::GetPortNumber() const
+uint16_t Socket::GetLocalPortNumber() const
+{
+ return GetLocalPortNumber (m_socket);
+}
+
+std::string Socket::GetLocalIPAddress () const
+{
+ // We bound to port zero, so we need to figure out which port we actually bound to
+ if (m_socket >= 0)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetIPAddress ();
+ }
+ return "";
+}
+
+uint16_t Socket::GetRemotePortNumber () const
{
- return GetPortNumber(m_socket);
+ if (m_socket >= 0)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetPort ();
+ }
+ return 0;
}
+
+std::string Socket::GetRemoteIPAddress () const
+{
+ // We bound to port zero, so we need to figure out which port we actually bound to
+ if (m_socket >= 0)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetIPAddress ();
+ }
+ return "";
+}
+
Index: source/Host/common/SocketAddress.cpp
===================================================================
--- source/Host/common/SocketAddress.cpp
+++ source/Host/common/SocketAddress.cpp
@@ -21,6 +21,56 @@
// Other libraries and framework includes
// Project includes
+// WindowsXP needs an inet_ntop implementation
+#ifdef _WIN32
+
+#ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs
+#define INET6_ADDRSTRLEN 46
+#endif
+
+// TODO: implement shortened form "::" for runs of zeros
+const char* inet_ntop(int af, const void * src,
+ char * dst, socklen_t size)
+{
+ if (size==0)
+ {
+ return nullptr;
+ }
+
+ switch (af)
+ {
+ case AF_INET:
+ {
+ const char* formatted = inet_ntoa(*static_cast<const in_addr*>(src));
+ if (strlen(formatted) < size)
+ {
+ strncpy(dst, formatted, size);
+ return dst;
+ }
+ return nullptr;
+ case AF_INET6:
+ {
+ char tmp[INET6_ADDRSTRLEN] = {0};
+ const uint16_t* src16 = static_cast<const uint16_t*>(src);
+ int full_size = _snprintf(tmp, sizeof(tmp),
+ "%x:%x:%x:%x:%x:%x:%x:%x",
+ ntohs(src16[0]), ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]),
+ ntohs(src16[4]), ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7])
+ );
+ if (full_size < size)
+ {
+ strncpy(dst,tmp,size);
+ return dst;
+ }
+ return nullptr;
+ }
+ }
+ return nullptr;
+ }
+
+#endif
+
+
using namespace lldb_private;
//----------------------------------------------------------------------
@@ -124,6 +174,26 @@
#endif
}
+std::string
+SocketAddress::GetIPAddress () const
+{
+ char str[INET6_ADDRSTRLEN] = {0};
+ switch (GetFamily())
+ {
+ case AF_INET:
+ if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, sizeof(str)))
+ {
+ return str;
+ }
+ case AF_INET6:
+ if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, sizeof(str)))
+ {
+ return str;
+ }
+ }
+ return "";
+}
+
uint16_t
SocketAddress::GetPort () const
{
Index: source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
===================================================================
--- source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -274,7 +274,7 @@
if (conn_ap->IsConnected())
{
const Socket& socket = static_cast<const Socket&>(*conn_ap->GetReadObject());
- const uint16_t reply_port = socket.GetPortNumber();
+ const uint16_t reply_port = socket.GetLocalPortNumber();
if (reply_port != 0)
{
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits