ovyalov created this revision.
ovyalov added reviewers: clayborg, labath.
ovyalov added a subscriber: lldb-commits.

Abstract domain sockets are supported only by Linux (at least, as documentation 
says) so I'm putting new socket class into linux subfolder.
Since there is a possibility that abstract namespace might be provided by other 
posix platforms it might be useful to link it with linux-independent URL scheme 
- i.e. "unix-abstract-connect".

http://reviews.llvm.org/D13970

Files:
  include/lldb/Host/Socket.h
  include/lldb/Host/linux/AbstractSocket.h
  include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
  include/lldb/Host/posix/DomainSocket.h
  source/Host/CMakeLists.txt
  source/Host/common/Socket.cpp
  source/Host/linux/AbstractSocket.cpp
  source/Host/posix/ConnectionFileDescriptorPosix.cpp
  source/Host/posix/DomainSocket.cpp

Index: source/Host/posix/DomainSocket.cpp
===================================================================
--- source/Host/posix/DomainSocket.cpp
+++ source/Host/posix/DomainSocket.cpp
@@ -29,14 +29,19 @@
 const int kDomain = AF_UNIX;
 const int kType   = SOCK_STREAM;
 
-void SetSockAddr(llvm::StringRef name, sockaddr_un* saddr_un)
+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;
-    ::strncpy(saddr_un->sun_path, name.data(), sizeof(saddr_un->sun_path) - 1);
-    saddr_un->sun_path[sizeof(saddr_un->sun_path) - 1] = '\0';
+    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;
 }
 
 }
@@ -51,14 +56,20 @@
 {
 }
 
+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;
-    SetSockAddr(name, &saddr_un);
+    if (!SetSockAddr(name, GetNameOffset(), &saddr_un))
+        return Error("Failed to set socket address");
 
     Error error;
-    if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
+    if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) < 0)
         SetLastError (error);
 
     return error;
@@ -68,12 +79,13 @@
 DomainSocket::Listen(llvm::StringRef name, int backlog)
 {
     sockaddr_un saddr_un;
-    SetSockAddr(name, &saddr_un);
+    if (!SetSockAddr(name, GetNameOffset(), &saddr_un))
+        return Error("Failed to set socket address");
 
-    FileSystem::Unlink(FileSpec{name, true});
+    DeleteSocketFile(name);
 
     Error error;
-    if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
+    if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, sizeof(saddr_un)) == 0)
         if (::listen(GetNativeSocket(), backlog) == 0)
             return error;
 
@@ -91,3 +103,15 @@
 
     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
@@ -186,6 +186,11 @@
             // unix-connect://SOCKNAME
             return NamedSocketConnect(s + strlen("unix-connect://"), error_ptr);
         }
+        else if (strstr(s, "unix-abstract-connect://") == s)
+        {
+            // unix-abstract-connect://SOCKNAME
+            return UnixAbstractSocketConnect(s + strlen("unix-abstract-connect://"), error_ptr);
+        }
 #ifndef LLDB_DISABLE_POSIX
         else if (strstr(s, "fd://") == s)
         {
@@ -763,6 +768,23 @@
     return eConnectionStatusSuccess;
 }
 
+lldb::ConnectionStatus
+ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr)
+{
+    Socket *socket = nullptr;
+    Error error = Socket::UnixAbstractConnect(socket_name, m_child_processes_inherit, socket);
+    if (error_ptr)
+        *error_ptr = error;
+    m_write_sp.reset(socket);
+    m_read_sp = m_write_sp;
+    if (error.Fail())
+    {
+        return eConnectionStatusError;
+    }
+    m_uri.assign(socket_name);
+    return eConnectionStatusSuccess;
+}
+
 ConnectionStatus
 ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr)
 {
Index: source/Host/linux/AbstractSocket.cpp
===================================================================
--- /dev/null
+++ source/Host/linux/AbstractSocket.cpp
@@ -0,0 +1,31 @@
+//===-- 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/Socket.cpp
===================================================================
--- source/Host/common/Socket.cpp
+++ source/Host/common/Socket.cpp
@@ -30,6 +30,10 @@
 #include <sys/un.h>
 #endif
 
+#ifdef __linux__
+#include "lldb/Host/linux/AbstractSocket.h"
+#endif
+
 #ifdef __ANDROID_NDK__
 #include <linux/tcp.h>
 #include <bits/error_constants.h>
@@ -190,6 +194,44 @@
     return error;
 }
 
+Error
+Socket::UnixAbstractConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+{
+    Error error;
+#ifdef __linux__
+    std::unique_ptr<Socket> connect_socket(new AbstractSocket(child_processes_inherit, error));
+    if (error.Fail())
+        return error;
+
+    error = connect_socket->Connect(name);
+    if (error.Success())
+      socket = connect_socket.release();
+#else
+    error.SetErrorString("Abstract domain sockets are not supported on this platform.");
+#endif
+    return error;
+}
+
+Error
+Socket::UnixAbstractAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+{
+    Error error;
+#ifdef __linux__
+    std::unique_ptr<Socket> listen_socket(new AbstractSocket(child_processes_inherit, error));
+    if (error.Fail())
+        return error;
+
+    error = listen_socket->Listen(name, 5);
+    if (error.Fail())
+        return error;
+
+    error = listen_socket->Accept(name, child_processes_inherit, socket);
+#else
+    error.SetErrorString("Abstract domain sockets are not supported on this platform.");
+#endif
+    return error;
+}
+
 bool
 Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
                           std::string &host_str,
Index: source/Host/CMakeLists.txt
===================================================================
--- source/Host/CMakeLists.txt
+++ source/Host/CMakeLists.txt
@@ -121,14 +121,16 @@
         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: include/lldb/Host/posix/DomainSocket.h
===================================================================
--- include/lldb/Host/posix/DomainSocket.h
+++ include/lldb/Host/posix/DomainSocket.h
@@ -22,6 +22,13 @@
         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);
     };
Index: include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
===================================================================
--- include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
+++ include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
@@ -84,6 +84,8 @@
 
     lldb::ConnectionStatus NamedSocketAccept(const char *socket_name, Error *error_ptr);
 
+    lldb::ConnectionStatus UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr);
+
     lldb::IOObjectSP m_read_sp;
     lldb::IOObjectSP m_write_sp;
 
Index: include/lldb/Host/linux/AbstractSocket.h
===================================================================
--- /dev/null
+++ include/lldb/Host/linux/AbstractSocket.h
@@ -0,0 +1,28 @@
+//===-- 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/Socket.h
===================================================================
--- include/lldb/Host/Socket.h
+++ include/lldb/Host/Socket.h
@@ -45,7 +45,8 @@
     {
         ProtocolTcp,
         ProtocolUdp,
-        ProtocolUnixDomain
+        ProtocolUnixDomain,
+        ProtocolUnixAbstract
     } SocketProtocol;
 
     static const NativeSocket kInvalidSocketValue;
@@ -69,6 +70,8 @@
     static Error UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket);
     static Error UnixDomainConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
     static Error UnixDomainAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
+    static Error UnixAbstractConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
+    static Error UnixAbstractAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
 
     int GetOption (int level, int option_name, int &option_value);
     int SetOption (int level, int option_name, int option_value);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to