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

Reply via email to