ovyalov created this revision.
ovyalov added a reviewer: clayborg.
ovyalov added a subscriber: lldb-commits.
Herald added subscribers: srhines, danalbert, tberghammer.

Make Socket to support plugin interface - moved implementation classes into 
source/Plugins/Socket folder and migrated most of use cases in order to rely on 
base Socket class.

http://reviews.llvm.org/D14085

Files:
  cmake/LLDBDependencies.cmake
  include/lldb/Core/PluginManager.h
  include/lldb/Host/Socket.h
  include/lldb/Host/common/TCPSocket.h
  include/lldb/Host/common/UDPSocket.h
  include/lldb/Host/linux/AbstractSocket.h
  include/lldb/Host/posix/DomainSocket.h
  include/lldb/lldb-forward.h
  include/lldb/lldb-private-interfaces.h
  lldb.xcodeproj/project.pbxproj
  source/Core/PluginManager.cpp
  source/Host/CMakeLists.txt
  source/Host/common/Socket.cpp
  source/Host/common/TCPSocket.cpp
  source/Host/common/UDPSocket.cpp
  source/Host/linux/AbstractSocket.cpp
  source/Host/posix/ConnectionFileDescriptorPosix.cpp
  source/Host/posix/DomainSocket.cpp
  source/Initialization/SystemInitializerCommon.cpp
  source/Plugins/CMakeLists.txt
  source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
  source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
  source/Plugins/Socket/CMakeLists.txt
  source/Plugins/Socket/Linux/AbstractSocket.cpp
  source/Plugins/Socket/Linux/AbstractSocket.h
  source/Plugins/Socket/Linux/CMakeLists.txt
  source/Plugins/Socket/POSIX/CMakeLists.txt
  source/Plugins/Socket/POSIX/DomainSocket.cpp
  source/Plugins/Socket/POSIX/DomainSocket.h
  source/Plugins/Socket/TCP/CMakeLists.txt
  source/Plugins/Socket/TCP/TCPSocket.cpp
  source/Plugins/Socket/TCP/TCPSocket.h
  source/Plugins/Socket/UDP/CMakeLists.txt
  source/Plugins/Socket/UDP/UDPSocket.cpp
  source/Plugins/Socket/UDP/UDPSocket.h
  tools/lldb-server/Acceptor.cpp
  tools/lldb-server/lldb-platform.cpp
  unittests/Host/SocketTest.cpp

Index: unittests/Host/SocketTest.cpp
===================================================================
--- unittests/Host/SocketTest.cpp
+++ unittests/Host/SocketTest.cpp
@@ -21,12 +21,8 @@
 
 #include "lldb/Host/Config.h"
 #include "lldb/Host/Socket.h"
-#include "lldb/Host/common/TCPSocket.h"
-#include "lldb/Host/common/UDPSocket.h"
 
-#ifndef LLDB_DISABLE_POSIX
-#include "lldb/Host/posix/DomainSocket.h"
-#endif
+#include "Plugins/Socket/UDP/UDPSocket.h"
 
 using namespace lldb_private;
 
@@ -40,6 +36,7 @@
         WSADATA data;
         ::WSAStartup(MAKEWORD(2, 2), &data);
 #endif
+        Socket::Initialize();
     }
 
     void
@@ -58,13 +55,12 @@
         *error = listen_socket->Accept(listen_remote_address, child_processes_inherit, *accept_socket);
     }
 
-    template<typename SocketType>
     void
-    CreateConnectedSockets(const char *listen_remote_address, const std::function<std::string(const SocketType&)> &get_connect_addr, std::unique_ptr<SocketType> *a_up, std::unique_ptr<SocketType> *b_up)
+    CreateConnectedSockets(const char* scheme, const char *listen_remote_address, const std::function<std::string(const Socket&)> &get_connect_addr, std::unique_ptr<Socket> *a_up, std::unique_ptr<Socket> *b_up)
     {
         bool child_processes_inherit = false;
         Error error;
-        std::unique_ptr<SocketType> listen_socket_up(new SocketType(child_processes_inherit, error));
+        std::unique_ptr<Socket> listen_socket_up(Socket::Create(scheme, child_processes_inherit, error));
         EXPECT_FALSE(error.Fail());
         error = listen_socket_up->Listen(listen_remote_address, 5);
         EXPECT_FALSE(error.Fail());
@@ -76,7 +72,7 @@
                                   &accept_socket, &accept_error);
 
         std::string connect_remote_address = get_connect_addr(*listen_socket_up);
-        std::unique_ptr<SocketType> connect_socket_up(new SocketType(child_processes_inherit, error));
+        std::unique_ptr<Socket> connect_socket_up(Socket::Create(scheme, child_processes_inherit, error));
         EXPECT_FALSE(error.Fail());
         error = connect_socket_up->Connect(connect_remote_address.c_str());
         EXPECT_FALSE(error.Fail());
@@ -88,7 +84,7 @@
         EXPECT_TRUE((*a_up)->IsValid());
 
         accept_thread.join();
-        b_up->reset(static_cast<SocketType*>(accept_socket));
+        b_up->reset(accept_socket);
         EXPECT_TRUE(accept_error.Success());
         EXPECT_NE(nullptr, b_up->get());
         EXPECT_TRUE((*b_up)->IsValid());
@@ -138,44 +134,47 @@
     const std::string file_name(file_name_str);
     free(file_name_str);
 
-    std::unique_ptr<DomainSocket> socket_a_up;
-    std::unique_ptr<DomainSocket> socket_b_up;
-    CreateConnectedSockets<DomainSocket>(file_name.c_str(),
-                                      [=](const DomainSocket &)
-                                      {
-                                          return file_name;
-                                      },
-                                      &socket_a_up, &socket_b_up);
+    std::unique_ptr<Socket> socket_a_up;
+    std::unique_ptr<Socket> socket_b_up;
+    CreateConnectedSockets("unix",
+                           file_name.c_str(),
+                           [=](const Socket &)
+                           {
+                               return file_name;
+                           },
+                           &socket_a_up, &socket_b_up);
 }
 #endif
 
 TEST_F (SocketTest, TCPListen0ConnectAccept)
 {
-    std::unique_ptr<TCPSocket> socket_a_up;
-    std::unique_ptr<TCPSocket> socket_b_up;
-    CreateConnectedSockets<TCPSocket>("127.0.0.1:0",
-                                      [=](const TCPSocket &s)
-                                      {
-                                          char connect_remote_address[64];
-                                          snprintf(connect_remote_address, sizeof(connect_remote_address), "localhost:%u", s.GetLocalPortNumber());
-                                          return std::string(connect_remote_address);
-                                      },
-                                      &socket_a_up, &socket_b_up);
+    std::unique_ptr<Socket> socket_a_up;
+    std::unique_ptr<Socket> socket_b_up;
+    CreateConnectedSockets("tcp",
+                           "127.0.0.1:0",
+                           [=](const Socket &s)
+                           {
+                               char connect_remote_address[64];
+                               snprintf(connect_remote_address, sizeof(connect_remote_address), "localhost:%u", s.GetLocalPortNumber());
+                               return std::string(connect_remote_address);
+                           },
+                           &socket_a_up, &socket_b_up);
 }
 
 TEST_F (SocketTest, TCPGetAddress)
 {
-    std::unique_ptr<TCPSocket> socket_a_up;
-    std::unique_ptr<TCPSocket> socket_b_up;
-    CreateConnectedSockets<TCPSocket>("127.0.0.1:0",
-                                      [=](const TCPSocket &s)
-                                      {
-                                          char connect_remote_address[64];
-                                          snprintf(connect_remote_address, sizeof(connect_remote_address), "localhost:%u", s.GetLocalPortNumber());
-                                          return std::string(connect_remote_address);
-                                      },
-                                      &socket_a_up,
-                                      &socket_b_up);
+    std::unique_ptr<Socket> socket_a_up;
+    std::unique_ptr<Socket> socket_b_up;
+    CreateConnectedSockets("tcp",
+                           "127.0.0.1:0",
+                           [=](const Socket &s)
+                           {
+                               char connect_remote_address[64];
+                               snprintf(connect_remote_address, sizeof(connect_remote_address), "localhost:%u", s.GetLocalPortNumber());
+                               return std::string(connect_remote_address);
+                           },
+                           &socket_a_up,
+                           &socket_b_up);
 
     EXPECT_EQ (socket_a_up->GetLocalPortNumber (), socket_b_up->GetRemotePortNumber ());
     EXPECT_EQ (socket_b_up->GetLocalPortNumber (), socket_a_up->GetRemotePortNumber ());
Index: tools/lldb-server/lldb-platform.cpp
===================================================================
--- tools/lldb-server/lldb-platform.cpp
+++ tools/lldb-server/lldb-platform.cpp
@@ -32,7 +32,6 @@
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostGetOpt.h"
 #include "lldb/Host/OptionParser.h"
-#include "lldb/Host/common/TCPSocket.h"
 #include "Acceptor.h"
 #include "LLDBServerUtilities.h"
 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
Index: tools/lldb-server/Acceptor.cpp
===================================================================
--- tools/lldb-server/Acceptor.cpp
+++ tools/lldb-server/Acceptor.cpp
@@ -13,8 +13,9 @@
 
 #include "lldb/Core/StreamString.h"
 #include "lldb/Host/ConnectionFileDescriptor.h"
-#include "lldb/Host/common/TCPSocket.h"
-#include "lldb/Host/posix/DomainSocket.h"
+#include "lldb/Host/Socket.h"
+
+#include "Utility/UriParser.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -65,20 +66,23 @@
     int32_t port = INT32_MIN;
     if (Socket::DecodeHostAndPort (name, host_str, port_str, port, &error))
     {
-        auto tcp_socket = new TCPSocket(child_processes_inherit, error);
-        local_socket_id = [tcp_socket]() {
-            auto local_port = tcp_socket->GetLocalPortNumber();
-            return (local_port != 0) ? std::to_string(local_port) : "";
-        };
-        listener_socket.reset(tcp_socket);
+        listener_socket = Socket::Create(Socket::TCP, child_processes_inherit, error);
+        if (error.Success())
+        {
+            auto tcp_socket = listener_socket.get();
+            local_socket_id = [tcp_socket]() {
+                auto local_port = tcp_socket->GetLocalPortNumber();
+                return (local_port != 0) ? std::to_string(local_port) : "";
+            };
+        }
     }
     else
     {
         const std::string socket_name = name;
         local_socket_id = [socket_name](){
             return socket_name;
         };
-        listener_socket.reset(new DomainSocket(child_processes_inherit, error));
+        listener_socket = Socket::Create(Socket::UNIX, child_processes_inherit, error);
     }
 
     if (error.Success())
Index: source/Plugins/Socket/UDP/UDPSocket.h
===================================================================
--- /dev/null
+++ source/Plugins/Socket/UDP/UDPSocket.h
@@ -0,0 +1,60 @@
+//===-- UDPSocket.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_UDPSocket_h_
+#define liblldb_UDPSocket_h_
+
+#include "lldb/Host/Socket.h"
+
+namespace lldb_private
+{
+    class UDPSocket: public Socket
+    {
+    public:
+        static Error Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket);
+
+        static void
+        Initialize();
+
+        static void
+        Terminate();
+
+        static lldb_private::ConstString
+        GetPluginNameStatic();
+
+        static const char *
+        GetPluginDescriptionStatic();
+
+        static Socket*
+        CreateInstance(bool child_processes_inherit, Error &error);
+
+        //------------------------------------------------------------------
+        // PluginInterface protocol
+        //------------------------------------------------------------------
+        ConstString
+        GetPluginName() override;
+
+        uint32_t
+        GetPluginVersion() override;
+
+        const char* GetScheme() const override;
+    private:
+        UDPSocket(NativeSocket socket);
+        UDPSocket(bool child_processes_inherit, Error &error);
+
+        size_t Send(const void *buf, const size_t num_bytes) override;
+        Error Connect(llvm::StringRef name) override;
+        Error Listen(llvm::StringRef name, int backlog) override;
+        Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override;
+
+        SocketAddress m_send_sockaddr;
+    };
+}
+
+#endif // ifndef liblldb_UDPSocket_h_
Index: source/Plugins/Socket/UDP/UDPSocket.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Socket/UDP/UDPSocket.cpp
@@ -0,0 +1,215 @@
+//===-- UdpSocket.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UDPSocket.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Config.h"
+
+#ifndef LLDB_DISABLE_POSIX
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#endif
+
+#include <memory>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+const int kDomain = AF_INET;
+const int kType   = SOCK_DGRAM;
+
+const Error kNotSupported("Not supported");
+
+}
+
+UDPSocket::UDPSocket(NativeSocket socket)
+    : Socket(socket, ProtocolUdp, true)
+{
+}
+
+UDPSocket::UDPSocket(bool child_processes_inherit, Error &error)
+    : UDPSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error))
+{
+}
+
+void
+UDPSocket::Initialize()
+{
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(),
+                                  CreateInstance);
+}
+
+void
+UDPSocket::Terminate()
+{
+}
+
+ConstString
+UDPSocket::GetPluginNameStatic()
+{
+    static ConstString g_name(UDP);
+    return g_name;
+}
+
+const char *
+UDPSocket::GetPluginDescriptionStatic()
+{
+    return "UDP socket plug-in";
+}
+
+Socket*
+UDPSocket::CreateInstance(bool child_processes_inherit, Error &error)
+{
+    error.Clear();
+    std::unique_ptr<Socket> socket_up(new UDPSocket(child_processes_inherit, error));
+    if (error.Fail())
+    {
+        socket_up.reset();
+        return nullptr;
+    }
+    return socket_up.release();
+}
+
+size_t
+UDPSocket::Send(const void *buf, const size_t num_bytes)
+{
+    return ::sendto (m_socket,
+                     static_cast<const char*>(buf),
+                     num_bytes,
+                     0,
+                     m_send_sockaddr,
+                     m_send_sockaddr.GetLength());
+}
+
+Error
+UDPSocket::Connect(llvm::StringRef name)
+{
+    return kNotSupported;
+}
+
+Error
+UDPSocket::Listen(llvm::StringRef name, int backlog)
+{
+    return kNotSupported;
+}
+
+Error
+UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+{
+    return kNotSupported;
+}
+
+Error
+UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket)
+{
+    std::unique_ptr<UDPSocket> final_send_socket;
+    std::unique_ptr<UDPSocket> final_recv_socket;
+
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+    if (log)
+        log->Printf ("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
+
+    Error error;
+    std::string host_str;
+    std::string port_str;
+    int32_t port = INT32_MIN;
+    if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
+        return error;
+
+    // Setup the receiving end of the UDP connection on this localhost
+    // on port zero. After we bind to port zero we can read the port.
+    final_recv_socket.reset(new UDPSocket(child_processes_inherit, error));
+    if (error.Success())
+    {
+        // Socket was created, now lets bind to the requested port
+        SocketAddress addr;
+        addr.SetToAnyAddress (AF_INET, 0);
+
+        if (::bind (final_recv_socket->GetNativeSocket(), addr, addr.GetLength()) == -1)
+        {
+            // Bind failed...
+            SetLastError (error);
+        }
+    }
+
+    assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid()));
+    if (error.Fail())
+        return error;
+
+    // At this point we have setup the receive port, now we need to
+    // setup the UDP send socket
+
+    struct addrinfo hints;
+    struct addrinfo *service_info_list = nullptr;
+
+    ::memset (&hints, 0, sizeof(hints));
+    hints.ai_family = kDomain;
+    hints.ai_socktype = kType;
+    int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list);
+    if (err != 0)
+    {
+        error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)",
+                                       host_str.c_str(),
+                                       port_str.c_str(),
+                                       err,
+                                       gai_strerror(err));
+        return error;
+    }
+
+    for (struct addrinfo *service_info_ptr = service_info_list;
+         service_info_ptr != nullptr;
+         service_info_ptr = service_info_ptr->ai_next)
+    {
+        auto send_fd = CreateSocket (service_info_ptr->ai_family,
+                                     service_info_ptr->ai_socktype,
+                                     service_info_ptr->ai_protocol,
+                                     child_processes_inherit,
+                                     error);
+        if (error.Success())
+        {
+            final_send_socket.reset(new UDPSocket(send_fd));
+            final_send_socket->m_send_sockaddr = service_info_ptr;
+            break;
+        }
+        else
+            continue;
+    }
+
+    :: freeaddrinfo (service_info_list);
+
+    if (!final_send_socket)
+        return error;
+
+    send_socket = final_send_socket.release();
+    recv_socket = final_recv_socket.release();
+    error.Clear();
+    return error;
+}
+
+ConstString
+UDPSocket::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+UDPSocket::GetPluginVersion()
+{
+    return 1;
+}
+
+const char* UDPSocket::GetScheme() const
+{
+    return GetPluginNameStatic().AsCString();
+}
Index: source/Plugins/Socket/UDP/CMakeLists.txt
===================================================================
--- /dev/null
+++ source/Plugins/Socket/UDP/CMakeLists.txt
@@ -0,0 +1,5 @@
+include_directories(.)
+
+add_lldb_library(lldbPluginUDPSocket
+  UDPSocket.cpp
+  )
Index: source/Plugins/Socket/TCP/TCPSocket.h
===================================================================
--- /dev/null
+++ source/Plugins/Socket/TCP/TCPSocket.h
@@ -0,0 +1,57 @@
+//===-- TCPSocket.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_TCPSocket_h_
+#define liblldb_TCPSocket_h_
+
+#include "lldb/Host/Socket.h"
+
+namespace lldb_private
+{
+    class TCPSocket: public Socket
+    {
+    public:
+        TCPSocket(NativeSocket socket, bool should_close);
+        TCPSocket(bool child_processes_inherit, Error &error);
+
+        static void
+        Initialize();
+
+        static void
+        Terminate();
+
+        static lldb_private::ConstString
+        GetPluginNameStatic();
+
+        static const char *
+        GetPluginDescriptionStatic();
+
+        static Socket*
+        CreateInstance(bool child_processes_inherit, Error &error);
+
+        int SetOptionNoDelay();
+        int SetOptionReuseAddress();
+
+        Error Connect(llvm::StringRef name) override;
+        Error Listen(llvm::StringRef name, int backlog) override;
+        Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket) override;
+        const char* GetScheme() const override;
+
+        //------------------------------------------------------------------
+        // PluginInterface protocol
+        //------------------------------------------------------------------
+        ConstString
+        GetPluginName() override;
+
+        uint32_t
+        GetPluginVersion() override;
+    };
+}
+
+#endif // ifndef liblldb_TCPSocket_h_
Index: source/Plugins/Socket/TCP/TCPSocket.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Socket/TCP/TCPSocket.cpp
@@ -0,0 +1,290 @@
+//===-- TcpSocket.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TCPSocket.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Config.h"
+
+#ifndef LLDB_DISABLE_POSIX
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+const int kDomain = AF_INET;
+const int kType   = SOCK_STREAM;
+
+}
+
+TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
+    : Socket(socket, ProtocolTcp, should_close)
+{
+
+}
+
+TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
+    : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, child_processes_inherit, error), true)
+{
+}
+
+
+void
+TCPSocket::Initialize()
+{
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(),
+                                  CreateInstance);
+}
+
+void
+TCPSocket::Terminate()
+{
+}
+
+ConstString
+TCPSocket::GetPluginNameStatic()
+{
+    static ConstString g_name(TCP);
+    return g_name;
+}
+
+const char *
+TCPSocket::GetPluginDescriptionStatic()
+{
+    return "TCP socket plug-in";
+}
+
+Socket*
+TCPSocket::CreateInstance(bool child_processes_inherit, Error &error)
+{
+    error.Clear();
+    std::unique_ptr<Socket> socket_up(new TCPSocket(child_processes_inherit, error));
+    if (error.Fail())
+    {
+        socket_up.reset();
+        return nullptr;
+    }
+    return socket_up.release();
+}
+
+Error
+TCPSocket::Connect(llvm::StringRef name)
+{
+    if (m_socket == kInvalidSocketValue)
+        return Error("Invalid socket");
+
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
+    if (log)
+        log->Printf ("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
+
+    Error error;
+    std::string host_str;
+    std::string port_str;
+    int32_t port = INT32_MIN;
+    if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
+        return error;
+
+    // Enable local address reuse
+    SetOptionReuseAddress();
+
+    struct sockaddr_in sa;
+    ::memset (&sa, 0, sizeof (sa));
+    sa.sin_family = kDomain;
+    sa.sin_port = htons (port);
+
+    int inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
+
+    if (inet_pton_result <= 0)
+    {
+        struct hostent *host_entry = gethostbyname (host_str.c_str());
+        if (host_entry)
+            host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
+        inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
+        if (inet_pton_result <= 0)
+        {
+            if (inet_pton_result == -1)
+                SetLastError(error);
+            else
+                error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
+
+            return error;
+        }
+    }
+
+    if (-1 == ::connect (GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa)))
+    {
+        SetLastError (error);
+        return error;
+    }
+
+    // Keep our TCP packets coming without any delays.
+    SetOptionNoDelay();
+    error.Clear();
+    return error;
+}
+
+Error
+TCPSocket::Listen(llvm::StringRef name, int backlog)
+{
+    Error error;
+
+    // enable local address reuse
+    SetOptionReuseAddress();
+
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+    if (log)
+        log->Printf ("TCPSocket::%s (%s)", __FUNCTION__, name.data());
+
+    std::string host_str;
+    std::string port_str;
+    int32_t port = INT32_MIN;
+    if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
+        return error;
+
+    SocketAddress bind_addr;
+
+    // Only bind to the loopback address if we are expecting a connection from
+    // localhost to avoid any firewall issues.
+    const bool bind_addr_success = (host_str == "127.0.0.1") ?
+                                    bind_addr.SetToLocalhost (kDomain, port) :
+                                    bind_addr.SetToAnyAddress (kDomain, port);
+
+    if (!bind_addr_success)
+    {
+        error.SetErrorString("Failed to bind port");
+        return error;
+    }
+
+    int err = ::bind (GetNativeSocket(), bind_addr, bind_addr.GetLength());
+    if (err != -1)
+        err = ::listen (GetNativeSocket(), backlog);
+
+    if (err == -1)
+        SetLastError (error);
+
+    return error;
+}
+
+Error
+TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket)
+{
+    Error error;
+    std::string host_str;
+    std::string port_str;
+    int32_t port;
+    if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
+        return error;
+
+    const sa_family_t family = kDomain;
+    const int socktype = kType;
+    const int protocol = IPPROTO_TCP;
+    SocketAddress listen_addr;
+    if (host_str.empty())
+        listen_addr.SetToLocalhost(family, port);
+    else if (host_str.compare("*") == 0)
+        listen_addr.SetToAnyAddress(family, port);
+    else
+    {
+        if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
+        {
+            error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
+            return error;
+        }
+    }
+
+    bool accept_connection = false;
+    std::unique_ptr<TCPSocket> accepted_socket;
+
+    // Loop until we are happy with our connection
+    while (!accept_connection)
+    {
+        struct sockaddr_in accept_addr;
+        ::memset (&accept_addr, 0, sizeof accept_addr);
+#if !(defined (__linux__) || defined(_WIN32))
+        accept_addr.sin_len = sizeof accept_addr;
+#endif
+        socklen_t accept_addr_len = sizeof accept_addr;
+
+        int sock = AcceptSocket (GetNativeSocket(),
+                                 (struct sockaddr *)&accept_addr,
+                                 &accept_addr_len,
+                                 child_processes_inherit,
+                                 error);
+
+        if (error.Fail())
+            break;
+
+        bool is_same_addr = true;
+#if !(defined(__linux__) || (defined(_WIN32)))
+        is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
+#endif
+        if (is_same_addr)
+            is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr);
+
+        if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY))
+        {
+            accept_connection = true;
+            accepted_socket.reset(new TCPSocket(sock, true));
+        }
+        else
+        {
+            const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
+            const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
+            ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
+                        accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
+                        listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
+            accepted_socket.reset();
+        }
+    }
+
+    if (!accepted_socket)
+        return error;
+
+    // Keep our TCP packets coming without any delays.
+    accepted_socket->SetOptionNoDelay();
+    error.Clear();
+    conn_socket = accepted_socket.release();
+    return error;
+}
+
+int
+TCPSocket::SetOptionNoDelay()
+{
+    return SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
+}
+
+int
+TCPSocket::SetOptionReuseAddress()
+{
+    return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
+}
+
+ConstString
+TCPSocket::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+TCPSocket::GetPluginVersion()
+{
+    return 1;
+}
+
+const char* TCPSocket::GetScheme() const
+{
+    return GetPluginNameStatic().AsCString();
+}
Index: source/Plugins/Socket/TCP/CMakeLists.txt
===================================================================
--- /dev/null
+++ source/Plugins/Socket/TCP/CMakeLists.txt
@@ -0,0 +1,5 @@
+include_directories(.)
+
+add_lldb_library(lldbPluginTCPSocket
+  TCPSocket.cpp
+  )
Index: source/Plugins/Socket/POSIX/DomainSocket.h
===================================================================
--- /dev/null
+++ source/Plugins/Socket/POSIX/DomainSocket.h
@@ -0,0 +1,62 @@
+//===-- DomainSocket.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DomainSocket_h_
+#define liblldb_DomainSocket_h_
+
+#include "lldb/Host/Socket.h"
+
+namespace lldb_private
+{
+    class DomainSocket: public Socket
+    {
+    public:
+        DomainSocket(bool child_processes_inherit, Error &error);
+
+        static void
+        Initialize();
+
+        static void
+        Terminate();
+
+        static lldb_private::ConstString
+        GetPluginNameStatic();
+
+        static const char *
+        GetPluginDescriptionStatic();
+
+        static Socket*
+        CreateInstance(bool child_processes_inherit, Error &error);
+
+        Error Connect(llvm::StringRef name) override;
+        Error Listen(llvm::StringRef name, int backlog) override;
+        Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override;
+        const char* GetScheme() const override;
+
+        //------------------------------------------------------------------
+        // PluginInterface protocol
+        //------------------------------------------------------------------
+        ConstString
+        GetPluginName() override;
+
+        uint32_t
+        GetPluginVersion() override;
+
+    protected:
+        DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error);
+
+        virtual size_t GetNameOffset() const;
+        virtual void DeleteSocketFile(llvm::StringRef name);
+
+    private:
+        DomainSocket(NativeSocket socket);
+    };
+}
+
+#endif // ifndef liblldb_DomainSocket_h_
Index: source/Plugins/Socket/POSIX/DomainSocket.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Socket/POSIX/DomainSocket.cpp
@@ -0,0 +1,174 @@
+//===-- DomainSocket.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DomainSocket.h"
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/FileSystem.h"
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+#ifdef __ANDROID__
+// Android does not have SUN_LEN
+#ifndef SUN_LEN
+#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
+#endif
+#endif // #ifdef __ANDROID__
+
+namespace {
+
+const int kDomain = AF_UNIX;
+const int kType   = SOCK_STREAM;
+
+bool SetSockAddr(llvm::StringRef name, const size_t name_offset, sockaddr_un* saddr_un)
+{
+    if (name.size() + name_offset > sizeof(saddr_un->sun_path))
+        return false;
+
+    saddr_un->sun_family = kDomain;
+    memset(saddr_un->sun_path, 0, sizeof(saddr_un->sun_path));
+
+    strncpy(&saddr_un->sun_path[name_offset], name.data(), name.size());
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+    saddr_un->sun_len = SUN_LEN (saddr_un);
+#endif
+    return true;
+}
+
+}
+
+DomainSocket::DomainSocket(NativeSocket socket)
+    : Socket(socket, ProtocolUnixDomain, true)
+{
+}
+
+DomainSocket::DomainSocket(bool child_processes_inherit, Error &error)
+    : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error))
+{
+}
+
+DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error)
+    : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true)
+{
+}
+
+void
+DomainSocket::Initialize()
+{
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(),
+                                  CreateInstance);
+}
+
+void
+DomainSocket::Terminate()
+{
+}
+
+ConstString
+DomainSocket::GetPluginNameStatic()
+{
+    static ConstString g_name(UNIX);
+    return g_name;
+}
+
+const char *
+DomainSocket::GetPluginDescriptionStatic()
+{
+    return "Unix domain socket plug-in";
+}
+
+Socket*
+DomainSocket::CreateInstance(bool child_processes_inherit, Error &error)
+{
+    error.Clear();
+    std::unique_ptr<Socket> socket_up(new DomainSocket(child_processes_inherit, error));
+    if (error.Fail())
+    {
+        socket_up.reset();
+        return nullptr;
+    }
+    return socket_up.release();
+}
+
+Error
+DomainSocket::Connect(llvm::StringRef name)
+{
+    sockaddr_un saddr_un;
+    if (!SetSockAddr(name, GetNameOffset(), &saddr_un))
+        return Error("Failed to set socket address");
+
+    Error error;
+    if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) < 0)
+        SetLastError (error);
+
+    return error;
+}
+
+Error
+DomainSocket::Listen(llvm::StringRef name, int backlog)
+{
+    sockaddr_un saddr_un;
+    if (!SetSockAddr(name, GetNameOffset(), &saddr_un))
+        return Error("Failed to set socket address");
+
+    DeleteSocketFile(name);
+
+    Error error;
+    if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) == 0)
+        if (::listen(GetNativeSocket(), backlog) == 0)
+            return error;
+
+    SetLastError(error);
+    return error;
+}
+
+Error
+DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+{
+    Error error;
+    auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error);
+    if (error.Success())
+        socket = new DomainSocket(conn_fd);
+
+    return error;
+}
+
+size_t
+DomainSocket::GetNameOffset() const
+{
+    return 0;
+}
+
+void
+DomainSocket::DeleteSocketFile(llvm::StringRef name)
+{
+    FileSystem::Unlink(FileSpec{name, true});
+}
+
+ConstString
+DomainSocket::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+DomainSocket::GetPluginVersion()
+{
+    return 1;
+}
+
+const char* DomainSocket::GetScheme() const
+{
+    return GetPluginNameStatic().AsCString();
+}
Index: source/Plugins/Socket/POSIX/CMakeLists.txt
===================================================================
--- /dev/null
+++ source/Plugins/Socket/POSIX/CMakeLists.txt
@@ -0,0 +1,5 @@
+include_directories(.)
+
+add_lldb_library(lldbPluginPOSIXSocket
+  DomainSocket.cpp
+  )
Index: source/Plugins/Socket/Linux/CMakeLists.txt
===================================================================
--- /dev/null
+++ source/Plugins/Socket/Linux/CMakeLists.txt
@@ -0,0 +1,5 @@
+include_directories(.)
+
+add_lldb_library(lldbPluginLinuxSocket
+  AbstractSocket.cpp
+  )
Index: source/Plugins/Socket/Linux/AbstractSocket.h
===================================================================
--- /dev/null
+++ source/Plugins/Socket/Linux/AbstractSocket.h
@@ -0,0 +1,54 @@
+//===-- AbstractSocket.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AbstractSocket_h_
+#define liblldb_AbstractSocket_h_
+
+#include "Plugins/Socket/POSIX/DomainSocket.h"
+
+namespace lldb_private
+{
+    class AbstractSocket: public DomainSocket
+    {
+    public:
+        AbstractSocket(bool child_processes_inherit, Error &error);
+
+        static void
+        Initialize();
+
+        static void
+        Terminate();
+
+        static lldb_private::ConstString
+        GetPluginNameStatic();
+
+        static const char *
+        GetPluginDescriptionStatic();
+
+        static Socket*
+        CreateInstance(bool child_processes_inherit, Error &error);
+
+        const char* GetScheme() const override;
+
+        //------------------------------------------------------------------
+        // PluginInterface protocol
+        //------------------------------------------------------------------
+        ConstString
+        GetPluginName() override;
+
+        uint32_t
+        GetPluginVersion() override;
+
+    protected:
+        size_t GetNameOffset() const override;
+        void DeleteSocketFile(llvm::StringRef name) override;
+    };
+}
+
+#endif // ifndef liblldb_AbstractSocket_h_
Index: source/Plugins/Socket/Linux/AbstractSocket.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Socket/Linux/AbstractSocket.cpp
@@ -0,0 +1,90 @@
+//===-- AbstractSocket.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AbstractSocket.h"
+
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+AbstractSocket::AbstractSocket(bool child_processes_inherit, Error &error)
+    : DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error)
+{
+}
+
+void
+AbstractSocket::Initialize()
+{
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(),
+                                  CreateInstance);
+}
+
+void
+AbstractSocket::Terminate()
+{
+}
+
+ConstString
+AbstractSocket::GetPluginNameStatic()
+{
+    static ConstString g_name(UNIX_ABSTRACT);
+    return g_name;
+}
+
+const char *
+AbstractSocket::GetPluginDescriptionStatic()
+{
+    return "Unix domain abstract socket plug-in";
+}
+
+Socket*
+AbstractSocket::CreateInstance(bool child_processes_inherit, Error &error)
+{
+    error.Clear();
+    std::unique_ptr<Socket> socket_up(new AbstractSocket(child_processes_inherit, error));
+    if (error.Fail())
+    {
+        socket_up.reset();
+        return nullptr;
+    }
+    return socket_up.release();
+}
+
+size_t
+AbstractSocket::GetNameOffset() const
+{
+    return 1;
+}
+
+void
+AbstractSocket::DeleteSocketFile(llvm::StringRef name)
+{
+}
+
+ConstString
+AbstractSocket::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+AbstractSocket::GetPluginVersion()
+{
+    return 1;
+}
+
+const char* AbstractSocket::GetScheme() const
+{
+    return GetPluginNameStatic().AsCString();
+}
Index: source/Plugins/Socket/CMakeLists.txt
===================================================================
--- /dev/null
+++ source/Plugins/Socket/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_subdirectory(TCP)
+add_subdirectory(UDP)
+if (CMAKE_HOST_UNIX)
+  add_subdirectory(POSIX)
+endif()
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+  add_subdirectory(Linux)
+endif()
Index: source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
===================================================================
--- source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -25,7 +25,7 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Host/Symbols.h"
 #include "lldb/Host/ThreadLauncher.h"
-#include "lldb/Host/common/TCPSocket.h"
+#include "lldb/Host/Socket.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandObject.h"
 #include "lldb/Interpreter/CommandObjectMultiword.h"
@@ -276,7 +276,7 @@
 
     if (conn_ap->IsConnected())
     {
-        const TCPSocket& socket = static_cast<const TCPSocket&>(*conn_ap->GetReadObject());
+        const Socket& socket = static_cast<const Socket&>(*conn_ap->GetReadObject());
         const uint16_t reply_port = socket.GetLocalPortNumber();
 
         if (reply_port != 0)
Index: source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
===================================================================
--- source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
+++ source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
@@ -10,7 +10,7 @@
 // Other libraries and framework includes
 #include "lldb/Core/Error.h"
 #include "lldb/Core/Log.h"
-#include "lldb/Host/common/TCPSocket.h"
+#include "lldb/Host/Socket.h"
 #include "AdbClient.h"
 #include "PlatformAndroidRemoteGDBServer.h"
 #include "Utility/UriParser.h"
@@ -63,7 +63,7 @@
 FindUnusedPort (uint16_t& port)
 {
     Error error;
-    std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(false, error));
+    const std::unique_ptr<Socket> tcp_socket(Socket::Create("tcp", false, error));
     if (error.Fail())
         return error;
 
Index: source/Plugins/CMakeLists.txt
===================================================================
--- source/Plugins/CMakeLists.txt
+++ source/Plugins/CMakeLists.txt
@@ -14,6 +14,7 @@
 add_subdirectory(Platform)
 add_subdirectory(Process)
 add_subdirectory(ScriptInterpreter)
+add_subdirectory(Socket)
 add_subdirectory(SymbolFile)
 add_subdirectory(SystemRuntime)
 add_subdirectory(SymbolVendor)
Index: source/Initialization/SystemInitializerCommon.cpp
===================================================================
--- source/Initialization/SystemInitializerCommon.cpp
+++ source/Initialization/SystemInitializerCommon.cpp
@@ -11,6 +11,7 @@
 
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
+#include "lldb/Host/Socket.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Timer.h"
 #include "lldb/Symbol/GoASTContext.h"
@@ -96,6 +97,7 @@
 
     Log::Initialize();
     HostInfo::Initialize();
+    Socket::Initialize();
     Timer::Initialize();
     Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
 
Index: source/Host/posix/DomainSocket.cpp
===================================================================
--- source/Host/posix/DomainSocket.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-//===-- DomainSocket.cpp ----------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Host/posix/DomainSocket.h"
-
-#include "lldb/Host/FileSystem.h"
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-using namespace lldb;
-using namespace lldb_private;
-
-#ifdef __ANDROID__
-// Android does not have SUN_LEN
-#ifndef SUN_LEN
-#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
-#endif
-#endif // #ifdef __ANDROID__
-
-namespace {
-
-const int kDomain = AF_UNIX;
-const int kType   = SOCK_STREAM;
-
-bool SetSockAddr(llvm::StringRef name, const size_t name_offset, sockaddr_un* saddr_un)
-{
-    if (name.size() + name_offset > sizeof(saddr_un->sun_path))
-        return false;
-
-    saddr_un->sun_family = kDomain;
-    memset(saddr_un->sun_path, 0, sizeof(saddr_un->sun_path));
-
-    strncpy(&saddr_un->sun_path[name_offset], name.data(), name.size());
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
-    saddr_un->sun_len = SUN_LEN (saddr_un);
-#endif
-    return true;
-}
-
-}
-
-DomainSocket::DomainSocket(NativeSocket socket)
-    : Socket(socket, ProtocolUnixDomain, true)
-{
-}
-
-DomainSocket::DomainSocket(bool child_processes_inherit, Error &error)
-    : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error))
-{
-}
-
-DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error)
-    : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true)
-{
-}
-
-Error
-DomainSocket::Connect(llvm::StringRef name)
-{
-    sockaddr_un saddr_un;
-    if (!SetSockAddr(name, GetNameOffset(), &saddr_un))
-        return Error("Failed to set socket address");
-
-    Error error;
-    if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) < 0)
-        SetLastError (error);
-
-    return error;
-}
-
-Error
-DomainSocket::Listen(llvm::StringRef name, int backlog)
-{
-    sockaddr_un saddr_un;
-    if (!SetSockAddr(name, GetNameOffset(), &saddr_un))
-        return Error("Failed to set socket address");
-
-    DeleteSocketFile(name);
-
-    Error error;
-    if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) == 0)
-        if (::listen(GetNativeSocket(), backlog) == 0)
-            return error;
-
-    SetLastError(error);
-    return error;
-}
-
-Error
-DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
-{
-    Error error;
-    auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error);
-    if (error.Success())
-        socket = new DomainSocket(conn_fd);
-
-    return error;
-}
-
-size_t
-DomainSocket::GetNameOffset() const
-{
-    return 0;
-}
-
-void
-DomainSocket::DeleteSocketFile(llvm::StringRef name)
-{
-    FileSystem::Unlink(FileSpec{name, true});
-}
Index: source/Host/posix/ConnectionFileDescriptorPosix.cpp
===================================================================
--- source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -47,8 +47,8 @@
 #include "lldb/Core/Timer.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/Socket.h"
-#include "lldb/Host/common/TCPSocket.h"
 #include "lldb/Interpreter/Args.h"
+#include "Plugins/Socket/TCP/TCPSocket.h"
 
 using namespace lldb;
 using namespace lldb_private;
Index: source/Host/linux/AbstractSocket.cpp
===================================================================
--- source/Host/linux/AbstractSocket.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===-- AbstractSocket.cpp --------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Host/linux/AbstractSocket.h"
-
-#include "llvm/ADT/StringRef.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-AbstractSocket::AbstractSocket(bool child_processes_inherit, Error &error)
-    : DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error)
-{
-}
-
-size_t
-AbstractSocket::GetNameOffset() const
-{
-    return 1;
-}
-
-void
-AbstractSocket::DeleteSocketFile(llvm::StringRef name)
-{
-}
Index: source/Host/common/UDPSocket.cpp
===================================================================
--- source/Host/common/UDPSocket.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-//===-- UdpSocket.cpp -------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Host/common/UDPSocket.h"
-
-#include "lldb/Core/Log.h"
-#include "lldb/Host/Config.h"
-
-#ifndef LLDB_DISABLE_POSIX
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#endif
-
-#include <memory>
-
-using namespace lldb;
-using namespace lldb_private;
-
-namespace {
-
-const int kDomain = AF_INET;
-const int kType   = SOCK_DGRAM;
-
-const Error kNotSupported("Not supported");
-
-}
-
-UDPSocket::UDPSocket(NativeSocket socket)
-    : Socket(socket, ProtocolUdp, true)
-{
-}
-
-UDPSocket::UDPSocket(bool child_processes_inherit, Error &error)
-    : UDPSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error))
-{
-}
-
-size_t
-UDPSocket::Send(const void *buf, const size_t num_bytes)
-{
-    return ::sendto (m_socket,
-                     static_cast<const char*>(buf),
-                     num_bytes,
-                     0,
-                     m_send_sockaddr,
-                     m_send_sockaddr.GetLength());
-}
-
-Error
-UDPSocket::Connect(llvm::StringRef name)
-{
-    return kNotSupported;
-}
-
-Error
-UDPSocket::Listen(llvm::StringRef name, int backlog)
-{
-    return kNotSupported;
-}
-
-Error
-UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
-{
-    return kNotSupported;
-}
-
-Error
-UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket)
-{
-    std::unique_ptr<UDPSocket> final_send_socket;
-    std::unique_ptr<UDPSocket> final_recv_socket;
-
-    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
-    if (log)
-        log->Printf ("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
-
-    Error error;
-    std::string host_str;
-    std::string port_str;
-    int32_t port = INT32_MIN;
-    if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
-        return error;
-
-    // Setup the receiving end of the UDP connection on this localhost
-    // on port zero. After we bind to port zero we can read the port.
-    final_recv_socket.reset(new UDPSocket(child_processes_inherit, error));
-    if (error.Success())
-    {
-        // Socket was created, now lets bind to the requested port
-        SocketAddress addr;
-        addr.SetToAnyAddress (AF_INET, 0);
-
-        if (::bind (final_recv_socket->GetNativeSocket(), addr, addr.GetLength()) == -1)
-        {
-            // Bind failed...
-            SetLastError (error);
-        }
-    }
-
-    assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid()));
-    if (error.Fail())
-        return error;
-
-    // At this point we have setup the receive port, now we need to
-    // setup the UDP send socket
-
-    struct addrinfo hints;
-    struct addrinfo *service_info_list = nullptr;
-
-    ::memset (&hints, 0, sizeof(hints));
-    hints.ai_family = kDomain;
-    hints.ai_socktype = kType;
-    int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list);
-    if (err != 0)
-    {
-        error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)",
-                                       host_str.c_str(),
-                                       port_str.c_str(),
-                                       err,
-                                       gai_strerror(err));
-        return error;
-    }
-
-    for (struct addrinfo *service_info_ptr = service_info_list;
-         service_info_ptr != nullptr;
-         service_info_ptr = service_info_ptr->ai_next)
-    {
-        auto send_fd = CreateSocket (service_info_ptr->ai_family,
-                                     service_info_ptr->ai_socktype,
-                                     service_info_ptr->ai_protocol,
-                                     child_processes_inherit,
-                                     error);
-        if (error.Success())
-        {
-            final_send_socket.reset(new UDPSocket(send_fd));
-            final_send_socket->m_send_sockaddr = service_info_ptr;
-            break;
-        }
-        else
-            continue;
-    }
-
-    :: freeaddrinfo (service_info_list);
-
-    if (!final_send_socket)
-        return error;
-
-    send_socket = final_send_socket.release();
-    recv_socket = final_recv_socket.release();
-    error.Clear();
-    return error;
-}
Index: source/Host/common/TCPSocket.cpp
===================================================================
--- source/Host/common/TCPSocket.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-//===-- TcpSocket.cpp -------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Host/common/TCPSocket.h"
-
-#include "lldb/Core/Log.h"
-#include "lldb/Host/Config.h"
-
-#ifndef LLDB_DISABLE_POSIX
-#include <arpa/inet.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h>
-#endif
-
-using namespace lldb;
-using namespace lldb_private;
-
-namespace {
-
-const int kDomain = AF_INET;
-const int kType   = SOCK_STREAM;
-
-}
-
-TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
-    : Socket(socket, ProtocolTcp, should_close)
-{
-
-}
-
-TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
-    : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, child_processes_inherit, error), true)
-{
-}
-
-
-// Return the port number that is being used by the socket.
-uint16_t
-TCPSocket::GetLocalPortNumber() const
-{
-    if (m_socket != kInvalidSocketValue)
-    {
-        SocketAddress sock_addr;
-        socklen_t sock_addr_len = sock_addr.GetMaxLength ();
-        if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
-            return sock_addr.GetPort ();
-    }
-    return 0;
-}
-
-std::string
-TCPSocket::GetLocalIPAddress() const
-{
-    // We bound to port zero, so we need to figure out which port we actually bound to
-    if (m_socket != kInvalidSocketValue)
-    {
-        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
-TCPSocket::GetRemotePortNumber() const
-{
-    if (m_socket != kInvalidSocketValue)
-    {
-        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
-TCPSocket::GetRemoteIPAddress () const
-{
-    // We bound to port zero, so we need to figure out which port we actually bound to
-    if (m_socket != kInvalidSocketValue)
-    {
-        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 "";
-}
-
-Error
-TCPSocket::Connect(llvm::StringRef name)
-{
-    if (m_socket == kInvalidSocketValue)
-        return Error("Invalid socket");
-
-    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
-    if (log)
-        log->Printf ("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
-
-    Error error;
-    std::string host_str;
-    std::string port_str;
-    int32_t port = INT32_MIN;
-    if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
-        return error;
-
-    // Enable local address reuse
-    SetOptionReuseAddress();
-
-    struct sockaddr_in sa;
-    ::memset (&sa, 0, sizeof (sa));
-    sa.sin_family = kDomain;
-    sa.sin_port = htons (port);
-
-    int inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
-
-    if (inet_pton_result <= 0)
-    {
-        struct hostent *host_entry = gethostbyname (host_str.c_str());
-        if (host_entry)
-            host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
-        inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
-        if (inet_pton_result <= 0)
-        {
-            if (inet_pton_result == -1)
-                SetLastError(error);
-            else
-                error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
-
-            return error;
-        }
-    }
-
-    if (-1 == ::connect (GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa)))
-    {
-        SetLastError (error);
-        return error;
-    }
-
-    // Keep our TCP packets coming without any delays.
-    SetOptionNoDelay();
-    error.Clear();
-    return error;
-}
-
-Error
-TCPSocket::Listen(llvm::StringRef name, int backlog)
-{
-    Error error;
-
-    // enable local address reuse
-    SetOptionReuseAddress();
-
-    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
-    if (log)
-        log->Printf ("TCPSocket::%s (%s)", __FUNCTION__, name.data());
-
-    std::string host_str;
-    std::string port_str;
-    int32_t port = INT32_MIN;
-    if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
-        return error;
-
-    SocketAddress bind_addr;
-
-    // Only bind to the loopback address if we are expecting a connection from
-    // localhost to avoid any firewall issues.
-    const bool bind_addr_success = (host_str == "127.0.0.1") ?
-                                    bind_addr.SetToLocalhost (kDomain, port) :
-                                    bind_addr.SetToAnyAddress (kDomain, port);
-
-    if (!bind_addr_success)
-    {
-        error.SetErrorString("Failed to bind port");
-        return error;
-    }
-
-    int err = ::bind (GetNativeSocket(), bind_addr, bind_addr.GetLength());
-    if (err != -1)
-        err = ::listen (GetNativeSocket(), backlog);
-
-    if (err == -1)
-        SetLastError (error);
-
-    return error;
-}
-
-Error
-TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket)
-{
-    Error error;
-    std::string host_str;
-    std::string port_str;
-    int32_t port;
-    if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
-        return error;
-
-    const sa_family_t family = kDomain;
-    const int socktype = kType;
-    const int protocol = IPPROTO_TCP;
-    SocketAddress listen_addr;
-    if (host_str.empty())
-        listen_addr.SetToLocalhost(family, port);
-    else if (host_str.compare("*") == 0)
-        listen_addr.SetToAnyAddress(family, port);
-    else
-    {
-        if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
-        {
-            error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
-            return error;
-        }
-    }
-
-    bool accept_connection = false;
-    std::unique_ptr<TCPSocket> accepted_socket;
-
-    // Loop until we are happy with our connection
-    while (!accept_connection)
-    {
-        struct sockaddr_in accept_addr;
-        ::memset (&accept_addr, 0, sizeof accept_addr);
-#if !(defined (__linux__) || defined(_WIN32))
-        accept_addr.sin_len = sizeof accept_addr;
-#endif
-        socklen_t accept_addr_len = sizeof accept_addr;
-
-        int sock = AcceptSocket (GetNativeSocket(),
-                                 (struct sockaddr *)&accept_addr,
-                                 &accept_addr_len,
-                                 child_processes_inherit,
-                                 error);
-
-        if (error.Fail())
-            break;
-
-        bool is_same_addr = true;
-#if !(defined(__linux__) || (defined(_WIN32)))
-        is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
-#endif
-        if (is_same_addr)
-            is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr);
-
-        if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY))
-        {
-            accept_connection = true;
-            accepted_socket.reset(new TCPSocket(sock, true));
-        }
-        else
-        {
-            const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
-            const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
-            ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
-                        accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
-                        listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
-            accepted_socket.reset();
-        }
-    }
-
-    if (!accepted_socket)
-        return error;
-
-    // Keep our TCP packets coming without any delays.
-    accepted_socket->SetOptionNoDelay();
-    error.Clear();
-    conn_socket = accepted_socket.release();
-    return error;
-}
-
-int
-TCPSocket::SetOptionNoDelay()
-{
-    return SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
-}
-
-int
-TCPSocket::SetOptionReuseAddress()
-{
-    return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
-}
Index: source/Host/common/Socket.cpp
===================================================================
--- source/Host/common/Socket.cpp
+++ source/Host/common/Socket.cpp
@@ -10,17 +10,19 @@
 #include "lldb/Host/Socket.h"
 
 #include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegularExpression.h"
 #include "lldb/Host/Config.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/SocketAddress.h"
 #include "lldb/Host/StringConvert.h"
 #include "lldb/Host/TimeValue.h"
-#include "lldb/Host/common/TCPSocket.h"
-#include "lldb/Host/common/UDPSocket.h"
+
+#include "Plugins/Socket/TCP/TCPSocket.h"
+#include "Plugins/Socket/UDP/UDPSocket.h"
 
 #ifndef LLDB_DISABLE_POSIX
-#include "lldb/Host/posix/DomainSocket.h"
+#include "Plugins/Socket/POSIX/DomainSocket.h"
 
 #include <arpa/inet.h>
 #include <netdb.h>
@@ -31,9 +33,11 @@
 #endif
 
 #ifdef __linux__
-#include "lldb/Host/linux/AbstractSocket.h"
+#include "Plugins/Socket/Linux/AbstractSocket.h"
 #endif
 
+#include <mutex>
+
 #ifdef __ANDROID_NDK__
 #include <linux/tcp.h>
 #include <bits/error_constants.h>
@@ -73,6 +77,11 @@
 
 }
 
+const char * Socket::TCP = "tcp";
+const char * Socket::UDP = "udp";
+const char * Socket::UNIX = "unix";
+const char * Socket::UNIX_ABSTRACT = "unix-abstract";
+
 Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close)
     : IOObject(eFDTypeSocket, should_close)
     , m_protocol(protocol)
@@ -86,20 +95,47 @@
     Close();
 }
 
+std::unique_ptr<Socket> Socket::Create(const char* scheme, bool child_processes_inherit, Error& error)
+{
+    ConstString const_plugin_name(scheme);
+    auto create_callback = PluginManager::GetSocketCreateCallbackForPluginName (const_plugin_name);
+    if (!create_callback)
+        return std::unique_ptr<Socket>();
+
+    return std::unique_ptr<Socket>(create_callback(child_processes_inherit, error));
+}
+
+void Socket::Initialize()
+{
+    static std::once_flag g_once_flag;
+    std::call_once(g_once_flag, [](){
+        TCPSocket::Initialize();
+        UDPSocket::Initialize();
+
+#ifndef LLDB_DISABLE_POSIX
+        DomainSocket::Initialize();
+#endif
+
+#ifdef __linux__
+        AbstractSocket::Initialize();
+#endif
+    });
+}
+
 Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket)
 {
     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
     if (log)
         log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data());
 
     Error error;
-    std::unique_ptr<TCPSocket> connect_socket(new TCPSocket(child_processes_inherit, error));
+    auto socket_up(Create(TCP, child_processes_inherit, error));
     if (error.Fail())
         return error;
 
-    error = connect_socket->Connect(host_and_port);
+    error = socket_up->Connect(host_and_port);
     if (error.Success())
-      socket = connect_socket.release();
+      socket = socket_up.release();
 
     return error;
 }
@@ -122,28 +158,28 @@
     if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
         return error;
 
-    std::unique_ptr<TCPSocket> listen_socket(new TCPSocket(child_processes_inherit, error));
+    auto socket_up(Create(TCP, child_processes_inherit, error));
     if (error.Fail())
         return error;
 
-    error = listen_socket->Listen(host_and_port, backlog);
+    error = socket_up->Listen(host_and_port, backlog);
     if (error.Success())
     {
         // We were asked to listen on port zero which means we
         // must now read the actual port that was given to us
         // as port zero is a special code for "find an open port
         // for me".
         if (port == 0)
-            port = listen_socket->GetLocalPortNumber();
+            port = socket_up->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);
-        socket = listen_socket.release();
+        socket = socket_up.release();
     }
 
     return error;
@@ -162,13 +198,13 @@
 {
     Error error;
 #ifndef LLDB_DISABLE_POSIX
-    std::unique_ptr<DomainSocket> connect_socket(new DomainSocket(child_processes_inherit, error));
+    auto socket_up(Create(UNIX, child_processes_inherit, error));
     if (error.Fail())
         return error;
 
-    error = connect_socket->Connect(name);
+    error = socket_up->Connect(name);
     if (error.Success())
-      socket = connect_socket.release();
+      socket = socket_up.release();
 #else
     error.SetErrorString("Unix domain sockets are not supported on this platform.");
 #endif
@@ -179,15 +215,15 @@
 {
     Error error;
 #ifndef LLDB_DISABLE_POSIX
-    std::unique_ptr<DomainSocket> listen_socket(new DomainSocket(child_processes_inherit, error));
+    auto socket_up(Create(UNIX, child_processes_inherit, error));
     if (error.Fail())
         return error;
 
-    error = listen_socket->Listen(name, 5);
+    error = socket_up->Listen(name, 5);
     if (error.Fail())
         return error;
 
-    error = listen_socket->Accept(name, child_processes_inherit, socket);
+    error = socket_up->Accept(name, child_processes_inherit, socket);
 #else
     error.SetErrorString("Unix domain sockets are not supported on this platform.");
 #endif
@@ -199,13 +235,13 @@
 {
     Error error;
 #ifdef __linux__
-    std::unique_ptr<Socket> connect_socket(new AbstractSocket(child_processes_inherit, error));
+    auto socket_up(Create(UNIX_ABSTRACT, child_processes_inherit, error));
     if (error.Fail())
         return error;
 
-    error = connect_socket->Connect(name);
+    error = socket_up->Connect(name);
     if (error.Success())
-      socket = connect_socket.release();
+      socket = socket_up.release();
 #else
     error.SetErrorString("Abstract domain sockets are not supported on this platform.");
 #endif
@@ -217,15 +253,15 @@
 {
     Error error;
 #ifdef __linux__
-    std::unique_ptr<Socket> listen_socket(new AbstractSocket(child_processes_inherit, error));
+    auto socket_up(Create(UNIX_ABSTRACT, child_processes_inherit, error));
     if (error.Fail())
         return error;
 
-    error = listen_socket->Listen(name, 5);
+    error = socket_up->Listen(name, 5);
     if (error.Fail())
         return error;
 
-    error = listen_socket->Accept(name, child_processes_inherit, socket);
+    error = socket_up->Accept(name, child_processes_inherit, socket);
 #else
     error.SetErrorString("Abstract domain sockets are not supported on this platform.");
 #endif
@@ -467,3 +503,58 @@
         SetLastError(error);
     return fd;
 }
+
+// Return the port number that is being used by the socket.
+uint16_t
+Socket::GetLocalPortNumber() const
+{
+    if (m_socket != kInvalidSocketValue)
+    {
+        SocketAddress sock_addr;
+        socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+        if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
+            return sock_addr.GetPort ();
+    }
+    return 0;
+}
+
+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 != kInvalidSocketValue)
+    {
+        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
+{
+    if (m_socket != kInvalidSocketValue)
+    {
+        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 != kInvalidSocketValue)
+    {
+        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/CMakeLists.txt
===================================================================
--- source/Host/CMakeLists.txt
+++ source/Host/CMakeLists.txt
@@ -34,13 +34,11 @@
   common/SoftwareBreakpoint.cpp
   common/StringConvert.cpp
   common/Symbols.cpp
-  common/TCPSocket.cpp
   common/Terminal.cpp
   common/ThisThread.cpp
   common/ThreadLauncher.cpp
   common/TimeValue.cpp
   common/XML.cpp
-  common/UDPSocket.cpp
   )
 
 # Keep track of whether we want to provide a define for the
@@ -83,7 +81,6 @@
   endif()
 
   add_host_subdirectory(posix
-    posix/DomainSocket.cpp
     posix/FileSystem.cpp
     posix/HostInfoPosix.cpp
     posix/HostProcessPosix.cpp
@@ -121,16 +118,14 @@
         android/HostInfoAndroid.cpp
         android/LibcGlue.cpp
         android/ProcessLauncherAndroid.cpp
-        linux/AbstractSocket.cpp
         linux/Host.cpp
         linux/HostInfoLinux.cpp
         linux/HostThreadLinux.cpp
         linux/LibcGlue.cpp
         linux/ThisThread.cpp
         )
     else()
       add_host_subdirectory(linux
-        linux/AbstractSocket.cpp
         linux/Host.cpp
         linux/HostInfoLinux.cpp
         linux/HostThreadLinux.cpp
Index: source/Core/PluginManager.cpp
===================================================================
--- source/Core/PluginManager.cpp
+++ source/Core/PluginManager.cpp
@@ -2780,6 +2780,93 @@
     return NULL;
 }
 
+#pragma mark Socket
+
+struct SocketInstance
+{
+    SocketInstance() :
+        name(),
+        description(),
+        create_callback(nullptr)
+    {
+    }
+
+    ConstString name;
+    std::string description;
+    SocketCreateInstance create_callback;
+};
+
+typedef std::vector<SocketInstance> SocketInstances;
+
+static Mutex &
+GetSocketMutex ()
+{
+    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+    return g_instances_mutex;
+}
+
+static SocketInstances &
+GetSocketInstances ()
+{
+    static SocketInstances g_instances;
+    return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin (const ConstString &name,
+                               const char *description,
+                               SocketCreateInstance create_callback)
+{
+    if (!create_callback)
+        return false;
+
+    SocketInstance instance;
+    assert ((bool)name);
+    instance.name = name;
+    if (description && description[0])
+        instance.description = description;
+    instance.create_callback = create_callback;
+    Mutex::Locker locker (GetSocketMutex ());
+    GetSocketInstances ().push_back (instance);
+    return true;
+}
+
+bool
+PluginManager::UnregisterPlugin (SocketCreateInstance create_callback)
+{
+    if (!create_callback)
+        return false;
+
+    Mutex::Locker locker (GetSocketMutex ());
+    SocketInstances &instances = GetSocketInstances ();
+
+    auto end = instances.end();
+    for (auto pos = instances.begin(); pos != end; ++pos)
+    {
+        if (pos->create_callback == create_callback)
+        {
+            instances.erase(pos);
+            return true;
+        }
+    }
+    return false;
+}
+
+SocketCreateInstance
+PluginManager::GetSocketCreateCallbackForPluginName (const ConstString &name)
+{
+    if (!name)
+        return nullptr;
+
+    Mutex::Locker locker (GetSocketMutex ());
+    for (auto pos: GetSocketInstances ())
+    {
+        if (name == pos.name)
+            return pos.create_callback;
+    }
+    return nullptr;
+}
+
 #pragma mark PluginManager
 
 void
Index: lldb.xcodeproj/project.pbxproj
===================================================================
--- lldb.xcodeproj/project.pbxproj
+++ lldb.xcodeproj/project.pbxproj
@@ -111,12 +111,17 @@
 		256CBDBA1ADD107200BC6CDC /* RegisterContextLinux_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 256CBDB61ADD107200BC6CDC /* RegisterContextLinux_arm.cpp */; };
 		256CBDBC1ADD107200BC6CDC /* RegisterContextLinux_mips64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 256CBDB81ADD107200BC6CDC /* RegisterContextLinux_mips64.cpp */; };
 		256CBDC01ADD11C000BC6CDC /* RegisterContextPOSIX_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 256CBDBE1ADD11C000BC6CDC /* RegisterContextPOSIX_arm.cpp */; };
-		2579065C1BD0488100178368 /* TCPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065A1BD0488100178368 /* TCPSocket.cpp */; };
-		2579065D1BD0488100178368 /* UDPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065B1BD0488100178368 /* UDPSocket.cpp */; };
-		2579065F1BD0488D00178368 /* DomainSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065E1BD0488D00178368 /* DomainSocket.cpp */; };
 		257906641BD5AFD000178368 /* Acceptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257906621BD5AFD000178368 /* Acceptor.cpp */; };
 		257906651BD5AFD000178368 /* Acceptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 257906631BD5AFD000178368 /* Acceptor.h */; };
 		257E47171AA56C2000A62F81 /* ModuleCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257E47151AA56C2000A62F81 /* ModuleCache.cpp */; };
+		25B4C4611BDEA2CD005B956D /* AbstractSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25B4C4521BDEA2CD005B956D /* AbstractSocket.cpp */; };
+		25B4C4621BDEA2CD005B956D /* AbstractSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B4C4531BDEA2CD005B956D /* AbstractSocket.h */; };
+		25B4C4631BDEA2CD005B956D /* DomainSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25B4C4571BDEA2CD005B956D /* DomainSocket.cpp */; };
+		25B4C4641BDEA2CD005B956D /* DomainSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B4C4581BDEA2CD005B956D /* DomainSocket.h */; };
+		25B4C4651BDEA2CD005B956D /* TCPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25B4C45B1BDEA2CD005B956D /* TCPSocket.cpp */; };
+		25B4C4661BDEA2CD005B956D /* TCPSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B4C45C1BDEA2CD005B956D /* TCPSocket.h */; };
+		25B4C4671BDEA2CD005B956D /* UDPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25B4C45F1BDEA2CD005B956D /* UDPSocket.cpp */; };
+		25B4C4681BDEA2CD005B956D /* UDPSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B4C4601BDEA2CD005B956D /* UDPSocket.h */; };
 		25EF23781AC09B3700908DF0 /* AdbClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25EF23751AC09AD800908DF0 /* AdbClient.cpp */; };
 		260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
 		260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
@@ -1231,13 +1236,23 @@
 		256CBDB91ADD107200BC6CDC /* RegisterContextLinux_mips64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextLinux_mips64.h; path = Utility/RegisterContextLinux_mips64.h; sourceTree = "<group>"; };
 		256CBDBE1ADD11C000BC6CDC /* RegisterContextPOSIX_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextPOSIX_arm.cpp; path = Utility/RegisterContextPOSIX_arm.cpp; sourceTree = "<group>"; };
 		256CBDBF1ADD11C000BC6CDC /* RegisterContextPOSIX_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextPOSIX_arm.h; path = Utility/RegisterContextPOSIX_arm.h; sourceTree = "<group>"; };
-		2579065A1BD0488100178368 /* TCPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TCPSocket.cpp; sourceTree = "<group>"; };
-		2579065B1BD0488100178368 /* UDPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UDPSocket.cpp; sourceTree = "<group>"; };
-		2579065E1BD0488D00178368 /* DomainSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DomainSocket.cpp; sourceTree = "<group>"; };
 		257906621BD5AFD000178368 /* Acceptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Acceptor.cpp; path = "tools/lldb-server/Acceptor.cpp"; sourceTree = "<group>"; };
 		257906631BD5AFD000178368 /* Acceptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Acceptor.h; path = "tools/lldb-server/Acceptor.h"; sourceTree = "<group>"; };
 		257E47151AA56C2000A62F81 /* ModuleCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleCache.cpp; path = source/Utility/ModuleCache.cpp; sourceTree = "<group>"; };
 		257E47161AA56C2000A62F81 /* ModuleCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleCache.h; path = source/Utility/ModuleCache.h; sourceTree = "<group>"; };
+		25B4C4501BDEA2CD005B956D /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
+		25B4C4521BDEA2CD005B956D /* AbstractSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractSocket.cpp; sourceTree = "<group>"; };
+		25B4C4531BDEA2CD005B956D /* AbstractSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractSocket.h; sourceTree = "<group>"; };
+		25B4C4541BDEA2CD005B956D /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
+		25B4C4561BDEA2CD005B956D /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
+		25B4C4571BDEA2CD005B956D /* DomainSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DomainSocket.cpp; sourceTree = "<group>"; };
+		25B4C4581BDEA2CD005B956D /* DomainSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DomainSocket.h; sourceTree = "<group>"; };
+		25B4C45A1BDEA2CD005B956D /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
+		25B4C45B1BDEA2CD005B956D /* TCPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TCPSocket.cpp; sourceTree = "<group>"; };
+		25B4C45C1BDEA2CD005B956D /* TCPSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCPSocket.h; sourceTree = "<group>"; };
+		25B4C45E1BDEA2CD005B956D /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
+		25B4C45F1BDEA2CD005B956D /* UDPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UDPSocket.cpp; sourceTree = "<group>"; };
+		25B4C4601BDEA2CD005B956D /* UDPSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UDPSocket.h; sourceTree = "<group>"; };
 		25EF23751AC09AD800908DF0 /* AdbClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdbClient.cpp; sourceTree = "<group>"; };
 		25EF23761AC09AD800908DF0 /* AdbClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdbClient.h; sourceTree = "<group>"; };
 		260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = "<absolute>"; };
@@ -3119,9 +3134,62 @@
 			path = FreeBSD;
 			sourceTree = "<group>";
 		};
+		25B4C44F1BDEA2CD005B956D /* Socket */ = {
+			isa = PBXGroup;
+			children = (
+				25B4C4501BDEA2CD005B956D /* CMakeLists.txt */,
+				25B4C4511BDEA2CD005B956D /* Linux */,
+				25B4C4551BDEA2CD005B956D /* POSIX */,
+				25B4C4591BDEA2CD005B956D /* TCP */,
+				25B4C45D1BDEA2CD005B956D /* UDP */,
+			);
+			path = Socket;
+			sourceTree = "<group>";
+		};
+		25B4C4511BDEA2CD005B956D /* Linux */ = {
+			isa = PBXGroup;
+			children = (
+				25B4C4521BDEA2CD005B956D /* AbstractSocket.cpp */,
+				25B4C4531BDEA2CD005B956D /* AbstractSocket.h */,
+				25B4C4541BDEA2CD005B956D /* CMakeLists.txt */,
+			);
+			path = Linux;
+			sourceTree = "<group>";
+		};
+		25B4C4551BDEA2CD005B956D /* POSIX */ = {
+			isa = PBXGroup;
+			children = (
+				25B4C4561BDEA2CD005B956D /* CMakeLists.txt */,
+				25B4C4571BDEA2CD005B956D /* DomainSocket.cpp */,
+				25B4C4581BDEA2CD005B956D /* DomainSocket.h */,
+			);
+			path = POSIX;
+			sourceTree = "<group>";
+		};
+		25B4C4591BDEA2CD005B956D /* TCP */ = {
+			isa = PBXGroup;
+			children = (
+				25B4C45A1BDEA2CD005B956D /* CMakeLists.txt */,
+				25B4C45B1BDEA2CD005B956D /* TCPSocket.cpp */,
+				25B4C45C1BDEA2CD005B956D /* TCPSocket.h */,
+			);
+			path = TCP;
+			sourceTree = "<group>";
+		};
+		25B4C45D1BDEA2CD005B956D /* UDP */ = {
+			isa = PBXGroup;
+			children = (
+				25B4C45E1BDEA2CD005B956D /* CMakeLists.txt */,
+				25B4C45F1BDEA2CD005B956D /* UDPSocket.cpp */,
+				25B4C4601BDEA2CD005B956D /* UDPSocket.h */,
+			);
+			path = UDP;
+			sourceTree = "<group>";
+		};
 		260C897110F57C5600BB2B04 /* Plugins */ = {
 			isa = PBXGroup;
 			children = (
+				25B4C44F1BDEA2CD005B956D /* Socket */,
 				8CF02ADD19DCBEC200B14BE0 /* InstrumentationRuntime */,
 				8C2D6A58197A1FB9006989C9 /* MemoryHistory */,
 				26DB3E051379E7AD0080DC73 /* ABI */,
@@ -5131,7 +5199,6 @@
 		3FDFDDC4199D37BE009756A7 /* posix */ = {
 			isa = PBXGroup;
 			children = (
-				2579065E1BD0488D00178368 /* DomainSocket.cpp */,
 				255EFF751AFABA950069F277 /* LockFilePosix.cpp */,
 				30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */,
 				AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */,
@@ -5338,8 +5405,6 @@
 		69A01E1A1236C5D400C660B5 /* common */ = {
 			isa = PBXGroup;
 			children = (
-				2579065A1BD0488100178368 /* TCPSocket.cpp */,
-				2579065B1BD0488100178368 /* UDPSocket.cpp */,
 				255EFF731AFABA720069F277 /* LockFileBase.cpp */,
 				250D6AE11A9679270049CC70 /* FileSystem.cpp */,
 				33E5E8411A672A240024ED68 /* StringConvert.cpp */,
@@ -5783,9 +5848,13 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				25B4C4641BDEA2CD005B956D /* DomainSocket.h in Headers */,
+				25B4C4661BDEA2CD005B956D /* TCPSocket.h in Headers */,
 				4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */,
 				257906651BD5AFD000178368 /* Acceptor.h in Headers */,
 				260A63171861008E00FECF8E /* IOHandler.h in Headers */,
+				25B4C4681BDEA2CD005B956D /* UDPSocket.h in Headers */,
+				25B4C4621BDEA2CD005B956D /* AbstractSocket.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -6302,6 +6371,7 @@
 				267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */,
 				2689FFF113353DB600698AC0 /* BreakpointID.cpp in Sources */,
 				AF77E0A91A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.cpp in Sources */,
+				25B4C4631BDEA2CD005B956D /* DomainSocket.cpp in Sources */,
 				2689FFF313353DB600698AC0 /* BreakpointIDList.cpp in Sources */,
 				2689FFF513353DB600698AC0 /* BreakpointList.cpp in Sources */,
 				AF77E08F1A033C700096C0EA /* ABISysV_ppc.cpp in Sources */,
@@ -6524,13 +6594,13 @@
 				2689008D13353E4200698AC0 /* DynamicLoaderMacOSXDYLD.cpp in Sources */,
 				2689008E13353E4200698AC0 /* DynamicLoaderStatic.cpp in Sources */,
 				2689009613353E4200698AC0 /* ObjectContainerBSDArchive.cpp in Sources */,
-				2579065D1BD0488100178368 /* UDPSocket.cpp in Sources */,
 				AE8F624919EF3E1E00326B21 /* OperatingSystemGo.cpp in Sources */,
 				26BC179A18C7F2B300D2196D /* JITLoaderList.cpp in Sources */,
 				2689009713353E4200698AC0 /* ObjectContainerUniversalMachO.cpp in Sources */,
 				2689009813353E4200698AC0 /* ELFHeader.cpp in Sources */,
 				2689009913353E4200698AC0 /* ObjectFileELF.cpp in Sources */,
 				2689009A13353E4200698AC0 /* ObjectFileMachO.cpp in Sources */,
+				25B4C4671BDEA2CD005B956D /* UDPSocket.cpp in Sources */,
 				2689009B13353E4200698AC0 /* PlatformMacOSX.cpp in Sources */,
 				2689009C13353E4200698AC0 /* PlatformRemoteiOS.cpp in Sources */,
 				2689009D13353E4200698AC0 /* GDBRemoteCommunication.cpp in Sources */,
@@ -6594,7 +6664,6 @@
 				268900D313353E6F00698AC0 /* ClangExternalASTSourceCallbacks.cpp in Sources */,
 				268900D513353E6F00698AC0 /* CompileUnit.cpp in Sources */,
 				268900D613353E6F00698AC0 /* Declaration.cpp in Sources */,
-				2579065C1BD0488100178368 /* TCPSocket.cpp in Sources */,
 				268900D713353E6F00698AC0 /* DWARFCallFrameInfo.cpp in Sources */,
 				268900D813353E6F00698AC0 /* Function.cpp in Sources */,
 				268900D913353E6F00698AC0 /* FuncUnwinders.cpp in Sources */,
@@ -6654,7 +6723,6 @@
 				94B6385D1B8FB178004FE1E4 /* CPlusPlusLanguage.cpp in Sources */,
 				268900FE13353E6F00698AC0 /* ThreadPlanCallUserExpression.cpp in Sources */,
 				268900FF13353E6F00698AC0 /* ThreadPlanShouldStopHere.cpp in Sources */,
-				2579065F1BD0488D00178368 /* DomainSocket.cpp in Sources */,
 				2689010013353E6F00698AC0 /* ThreadPlanStepInstruction.cpp in Sources */,
 				232CB61B191E00CD00EF39FC /* NativeThreadProtocol.cpp in Sources */,
 				2689010113353E6F00698AC0 /* ThreadPlanStepOut.cpp in Sources */,
@@ -6790,6 +6858,7 @@
 				949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */,
 				B27318421416AC12006039C8 /* WatchpointList.cpp in Sources */,
 				26CFDCA3186163A4000E63E5 /* Editline.cpp in Sources */,
+				25B4C4611BDEA2CD005B956D /* AbstractSocket.cpp in Sources */,
 				26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */,
 				B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */,
 				94B638631B8FB7F1004FE1E4 /* ObjCPlusPlusLanguage.cpp in Sources */,
@@ -6820,6 +6889,7 @@
 				26B1EFAE154638AF00E2DAC7 /* DWARFDeclContext.cpp in Sources */,
 				945215DF17F639EE00521C0B /* ValueObjectPrinter.cpp in Sources */,
 				260CC64815D0440D002BF2E0 /* OptionValueArgs.cpp in Sources */,
+				25B4C4651BDEA2CD005B956D /* TCPSocket.cpp in Sources */,
 				260CC64915D0440D002BF2E0 /* OptionValueArray.cpp in Sources */,
 				260CC64A15D0440D002BF2E0 /* OptionValueBoolean.cpp in Sources */,
 				260CC64B15D0440D002BF2E0 /* OptionValueProperties.cpp in Sources */,
Index: include/lldb/lldb-private-interfaces.h
===================================================================
--- include/lldb/lldb-private-interfaces.h
+++ include/lldb/lldb-private-interfaces.h
@@ -52,6 +52,7 @@
     typedef lldb::REPLSP (*REPLCreateInstance) (Error &error, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options);
     typedef void (*TypeSystemEnumerateSupportedLanguages) (std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions);
     typedef void (*REPLEnumerateSupportedLanguages) (std::set<lldb::LanguageType> &languages);
+    typedef Socket* (*SocketCreateInstance) (bool child_processes_inherit, Error &error);
     typedef int (*ComparisonFunction)(const void *, const void *);
     typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
 
Index: include/lldb/lldb-forward.h
===================================================================
--- include/lldb/lldb-forward.h
+++ include/lldb/lldb-forward.h
@@ -195,6 +195,7 @@
 class   SectionLoadHistory;
 class   SectionLoadList;
 class   Settings;
+class   Socket;
 class   SourceManager;
 class   SourceManagerImpl;
 class   StackFrame;
Index: include/lldb/Host/posix/DomainSocket.h
===================================================================
--- include/lldb/Host/posix/DomainSocket.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===-- DomainSocket.h ------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_DomainSocket_h_
-#define liblldb_DomainSocket_h_
-
-#include "lldb/Host/Socket.h"
-
-namespace lldb_private
-{
-    class DomainSocket: public Socket
-    {
-    public:
-        DomainSocket(bool child_processes_inherit, Error &error);
-
-        Error Connect(llvm::StringRef name) override;
-        Error Listen(llvm::StringRef name, int backlog) override;
-        Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override;
-
-    protected:
-        DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error);
-
-        virtual size_t GetNameOffset() const;
-        virtual void DeleteSocketFile(llvm::StringRef name);
-
-    private:
-        DomainSocket(NativeSocket socket);
-    };
-}
-
-#endif // ifndef liblldb_DomainSocket_h_
Index: include/lldb/Host/linux/AbstractSocket.h
===================================================================
--- include/lldb/Host/linux/AbstractSocket.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//===-- AbstractSocket.h ----------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_AbstractSocket_h_
-#define liblldb_AbstractSocket_h_
-
-#include "lldb/Host/posix/DomainSocket.h"
-
-namespace lldb_private
-{
-    class AbstractSocket: public DomainSocket
-    {
-    public:
-        AbstractSocket(bool child_processes_inherit, Error &error);
-
-    protected:
-        size_t GetNameOffset() const override;
-        void DeleteSocketFile(llvm::StringRef name) override;
-    };
-}
-
-#endif // ifndef liblldb_AbstractSocket_h_
Index: include/lldb/Host/common/UDPSocket.h
===================================================================
--- include/lldb/Host/common/UDPSocket.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- UDPSocket.h ---------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_UDPSocket_h_
-#define liblldb_UDPSocket_h_
-
-#include "lldb/Host/Socket.h"
-
-namespace lldb_private
-{
-    class UDPSocket: public Socket
-    {
-    public:
-        static Error Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket);
-
-    private:
-        UDPSocket(NativeSocket socket);
-        UDPSocket(bool child_processes_inherit, Error &error);
-
-        size_t Send(const void *buf, const size_t num_bytes) override;
-        Error Connect(llvm::StringRef name) override;
-        Error Listen(llvm::StringRef name, int backlog) override;
-        Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override;
-
-        SocketAddress m_send_sockaddr;
-    };
-}
-
-#endif // ifndef liblldb_UDPSocket_h_
Index: include/lldb/Host/common/TCPSocket.h
===================================================================
--- include/lldb/Host/common/TCPSocket.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//===-- TCPSocket.h ---------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_TCPSocket_h_
-#define liblldb_TCPSocket_h_
-
-#include "lldb/Host/Socket.h"
-
-namespace lldb_private
-{
-    class TCPSocket: public Socket
-    {
-    public:
-        TCPSocket(NativeSocket socket, bool should_close);
-        TCPSocket(bool child_processes_inherit, Error &error);
-
-        // 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;
-
-        int SetOptionNoDelay();
-        int SetOptionReuseAddress();
-
-        Error Connect(llvm::StringRef name) override;
-        Error Listen(llvm::StringRef name, int backlog) override;
-        Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket) override;
-    };
-}
-
-#endif // ifndef liblldb_TCPSocket_h_
Index: include/lldb/Host/Socket.h
===================================================================
--- include/lldb/Host/Socket.h
+++ include/lldb/Host/Socket.h
@@ -10,11 +10,13 @@
 #ifndef liblldb_Host_Socket_h_
 #define liblldb_Host_Socket_h_
 
+#include <memory>
 #include <string>
 
 #include "lldb/lldb-private.h"
 
 #include "lldb/Core/Error.h"
+#include "lldb/Core/PluginInterface.h"
 #include "lldb/Host/IOObject.h"
 #include "lldb/Host/Predicate.h"
 #include "lldb/Host/SocketAddress.h"
@@ -38,7 +40,8 @@
     typedef int NativeSocket;
 #endif
 
-class Socket : public IOObject
+class Socket : public IOObject,
+               public PluginInterface
 {
 public:
     typedef enum
@@ -49,10 +52,20 @@
         ProtocolUnixAbstract
     } SocketProtocol;
 
+    static const char *TCP;
+    static const char *UDP;
+    static const char *UNIX;
+    static const char *UNIX_ABSTRACT;
+
     static const NativeSocket kInvalidSocketValue;
 
     ~Socket() override;
 
+    static std::unique_ptr<Socket> Create(const char* scheme, bool child_processes_inherit, Error& error);
+
+    static void
+    Initialize();
+
     virtual Error Connect(llvm::StringRef name) = 0;
     virtual Error Listen(llvm::StringRef name, int backlog) = 0;
     virtual Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) = 0;
@@ -78,6 +91,7 @@
 
     NativeSocket GetNativeSocket () const { return m_socket; }
     SocketProtocol GetSocketProtocol () const { return m_protocol; }
+    virtual const char* GetScheme() const = 0;
 
     Error Read (void *buf, size_t &num_bytes) override;
     Error Write (const void *buf, size_t &num_bytes) override;
@@ -95,6 +109,20 @@
                        int32_t& port,
                        Error *error_ptr);
 
+    // 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;
+
 protected:
     Socket(NativeSocket socket, SocketProtocol protocol, bool should_close);
 
@@ -108,7 +136,7 @@
 
     SocketProtocol m_protocol;
     NativeSocket m_socket;
-};
+ };
 
 } // namespace lldb_private
 
Index: include/lldb/Core/PluginManager.h
===================================================================
--- include/lldb/Core/PluginManager.h
+++ include/lldb/Core/PluginManager.h
@@ -466,7 +466,21 @@
     
     static REPLEnumerateSupportedLanguages
     GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name);
-    
+
+    //------------------------------------------------------------------
+    // Socket
+    //------------------------------------------------------------------
+    static bool
+    RegisterPlugin (const ConstString &name,
+                    const char *description,
+                    SocketCreateInstance create_callback);
+
+    static bool
+    UnregisterPlugin (SocketCreateInstance create_callback);
+
+    static SocketCreateInstance
+    GetSocketCreateCallbackForPluginName (const ConstString &name);
+
     //------------------------------------------------------------------
     // Some plug-ins might register a DebuggerInitializeCallback
     // callback when registering the plug-in. After a new Debugger
Index: cmake/LLDBDependencies.cmake
===================================================================
--- cmake/LLDBDependencies.cmake
+++ cmake/LLDBDependencies.cmake
@@ -74,6 +74,8 @@
   lldbPluginProcessElfCore
   lldbPluginJITLoaderGDB
   lldbPluginExpressionParserClang
+  lldbPluginTCPSocket
+  lldbPluginUDPSocket
   )
 
 # Windows-only libraries
@@ -91,14 +93,17 @@
   list(APPEND LLDB_USED_LIBS
     lldbPluginProcessLinux
     lldbPluginProcessPOSIX
+    lldbPluginLinuxSocket
+    lldbPluginPOSIXSocket
    )
 endif ()
 
 # FreeBSD-only libraries
 if ( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" )
   list(APPEND LLDB_USED_LIBS
     lldbPluginProcessFreeBSD
     lldbPluginProcessPOSIX
+    lldbPluginPOSIXSocket
     )
 endif ()
 
@@ -110,6 +115,7 @@
     lldbPluginProcessMachCore
     lldbPluginProcessMacOSXKernel
     lldbPluginSymbolVendorMacOSX
+    lldbPluginPOSIXSocket
     )
 endif()
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to