Skip to content

Commit

Permalink
Creates a socket host object.
Browse files Browse the repository at this point in the history
This patch moves the logic of many common socket operations into
its own class lldb_private::Socket.  It then modifies the
ConnectionFileDescriptor class, and a few users of that class,
to use this new Socket class instead of hardcoding socket logic
directly.

Finally, this patch creates a common interface called IOObject for
any objects that support reading and writing, so that endpoints
such as sockets and files can be treated the same.

Differential Revision: http://reviews.llvm.org/D4641

Reviewed by: Todd Fiala, Greg Clayton

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@214984 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Zachary Turner committed Aug 6, 2014
1 parent db3cb6a commit d5832f8
Show file tree
Hide file tree
Showing 16 changed files with 1,078 additions and 1,006 deletions.
81 changes: 24 additions & 57 deletions include/lldb/Core/ConnectionFileDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,23 @@
#ifndef liblldb_ConnectionFileDescriptor_h_
#define liblldb_ConnectionFileDescriptor_h_

// C Includes
#ifndef _WIN32
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#endif

// C++ Includes
#include <memory>

#include "lldb/lldb-forward.h"

// Other libraries and framework includes
// Project includes
#include "lldb/Core/Connection.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/Predicate.h"
#include "lldb/Host/IOObject.h"

namespace lldb_private {

class Error;
class Socket;
class SocketAddress;

class ConnectionFileDescriptor :
Expand Down Expand Up @@ -65,33 +63,18 @@ class ConnectionFileDescriptor :
lldb::ConnectionStatus &status,
Error *error_ptr);

// If the read file descriptor is a socket, then return
// the port number that is being used by the socket.
uint16_t
GetReadPort () const;

// If the write file descriptor is a socket, then return
// the port number that is being used by the socket.
uint16_t
GetWritePort () const;

uint16_t
GetBoundPort (uint32_t timeout_sec);

lldb::ConnectionStatus
BytesAvailable (uint32_t timeout_usec, Error *error_ptr);

bool
InterruptRead ();

protected:
lldb::IOObjectSP GetReadObject() { return m_read_sp; }
const lldb::IOObjectSP GetReadObject() const { return m_read_sp; }

uint16_t GetListeningPort(uint32_t timeout_sec);

typedef enum
{
eFDTypeFile, // Other FD requiring read/write
eFDTypeSocket, // Socket requiring send/recv
eFDTypeSocketUDP // Unconnected UDP socket requiring sendto/recvfrom
} FDType;
protected:

void
OpenCommandPipe ();
Expand All @@ -101,47 +84,31 @@ class ConnectionFileDescriptor :

lldb::ConnectionStatus
SocketListen (const char *host_and_port, Error *error_ptr);

lldb::ConnectionStatus
ConnectTCP (const char *host_and_port, Error *error_ptr);

lldb::ConnectionStatus
ConnectUDP (const char *args, Error *error_ptr);

lldb::ConnectionStatus
NamedSocketAccept (const char *socket_name, Error *error_ptr);

lldb::ConnectionStatus
NamedSocketConnect (const char *socket_name, Error *error_ptr);

lldb::ConnectionStatus
Close (int& fd, FDType type, Error *error);

int m_fd_send;
int m_fd_recv;
FDType m_fd_send_type;
FDType m_fd_recv_type;
std::unique_ptr<SocketAddress> m_udp_send_sockaddr;
uint32_t m_socket_timeout_usec;
Pipe m_pipe;
Mutex m_mutex;
Predicate<uint16_t> m_port_predicate; // Used when binding to port zero to wait for the thread that creates the socket, binds and listens to resolve the port number
bool m_should_close_fd; // True if this class should close the file descriptor when it goes away.
bool m_shutting_down; // This marks that we are shutting down so if we get woken up from BytesAvailable
// to disconnect, we won't try to read again.
NamedSocketAccept (const char *socket_name, Error *error_ptr);

static uint16_t
GetSocketPort (int fd);

static int
GetSocketOption(int fd, int level, int option_name, int &option_value);

static int
SetSocketOption(int fd, int level, int option_name, int option_value);
lldb::IOObjectSP m_read_sp;
lldb::IOObjectSP m_write_sp;

bool
SetSocketReceiveTimeout (uint32_t timeout_usec);
Predicate<uint16_t> m_port_predicate; // Used when binding to port zero to wait for the thread
// that creates the socket, binds and listens to resolve
// the port number.

Pipe m_pipe;
Mutex m_mutex;
bool m_shutting_down; // This marks that we are shutting down so if we get woken up from
// BytesAvailable to disconnect, we won't try to read again.
bool m_waiting_for_accept;
private:
DISALLOW_COPY_AND_ASSIGN (ConnectionFileDescriptor);
};
Expand Down
1 change: 1 addition & 0 deletions include/lldb/Host/Editline.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "lldb/Host/Condition.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Predicate.h"

namespace lldb_private {

Expand Down
16 changes: 10 additions & 6 deletions include/lldb/Host/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <sys/types.h>

#include "lldb/lldb-private.h"
#include "lldb/Host/IOObject.h"

namespace lldb_private {

Expand All @@ -26,7 +27,7 @@ namespace lldb_private {
/// A file class that divides abstracts the LLDB core from host file
/// functionality.
//----------------------------------------------------------------------
class File
class File : public IOObject
{
public:
static int kInvalidDescriptor;
Expand All @@ -48,22 +49,22 @@ class File
ConvertOpenOptionsForPOSIXOpen (uint32_t open_options);

File() :
IOObject(eFDTypeFile, false),
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
m_options (0),
m_own_stream (false),
m_own_descriptor (false),
m_is_interactive (eLazyBoolCalculate),
m_is_real_terminal (eLazyBoolCalculate)
{
}

File (FILE *fh, bool transfer_ownership) :
IOObject(eFDTypeFile, false),
m_descriptor (kInvalidDescriptor),
m_stream (fh),
m_options (0),
m_own_stream (transfer_ownership),
m_own_descriptor (false),
m_is_interactive (eLazyBoolCalculate),
m_is_real_terminal (eLazyBoolCalculate)
{
Expand Down Expand Up @@ -118,11 +119,11 @@ class File
uint32_t permissions = lldb::eFilePermissionsFileDefault);

File (int fd, bool transfer_ownership) :
IOObject(eFDTypeFile, transfer_ownership),
m_descriptor (fd),
m_stream (kInvalidStream),
m_options (0),
m_own_stream (false),
m_own_descriptor (transfer_ownership)
m_own_stream (false)
{
}

Expand Down Expand Up @@ -222,6 +223,10 @@ class File
int
GetDescriptor() const;

WaitableHandle
GetWaitableHandle();


void
SetDescriptor(int fd, bool transfer_ownership);

Expand Down Expand Up @@ -541,7 +546,6 @@ class File
FILE *m_stream;
uint32_t m_options;
bool m_own_stream;
bool m_own_descriptor;
LazyBool m_is_interactive;
LazyBool m_is_real_terminal;
};
Expand Down
61 changes: 61 additions & 0 deletions include/lldb/Host/IOObject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//===-- IOObject.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_Host_Common_IOObject_h_
#define liblldb_Host_Common_IOObject_h_

#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>

#include "lldb/lldb-private.h"

namespace lldb_private {

class IOObject
{
public:
typedef enum
{
eFDTypeFile, // Other FD requiring read/write
eFDTypeSocket, // Socket requiring send/recv
} FDType;

// TODO: On Windows this should be a HANDLE, and wait should use
// WaitForMultipleObjects
typedef int WaitableHandle;
static const WaitableHandle kInvalidHandleValue;

IOObject(FDType type, bool should_close)
: m_fd_type(type)
, m_should_close_fd(should_close)
{
}
virtual ~IOObject() {}

virtual Error Read (void *buf, size_t &num_bytes) = 0;
virtual Error Write (const void *buf, size_t &num_bytes) = 0;
virtual bool IsValid() const = 0;
virtual Error Close() = 0;

FDType GetFdType() const { return m_fd_type; }

virtual WaitableHandle GetWaitableHandle() = 0;

protected:
FDType m_fd_type;
bool m_should_close_fd; // True if this class should close the file descriptor when it goes away.

private:
DISALLOW_COPY_AND_ASSIGN (IOObject);
};

}

#endif
103 changes: 103 additions & 0 deletions include/lldb/Host/Socket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//===-- Socket.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_Host_Socket_h_
#define liblldb_Host_Socket_h_

#include <string>

#include "lldb/lldb-private.h"

#include "lldb/Core/Error.h"
#include "lldb/Host/IOObject.h"
#include "lldb/Host/Predicate.h"
#include "lldb/Host/SocketAddress.h"

#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#endif

namespace llvm
{
class StringRef;
}

namespace lldb_private {

#if defined(_MSC_VER)
typedef SOCKET NativeSocket;
#else
typedef int NativeSocket;
#endif

class Socket : public IOObject
{
public:
typedef enum
{
ProtocolTcp,
ProtocolUdp,
ProtocolUnixDomain
} SocketProtocol;

static const NativeSocket kInvalidSocketValue;

Socket(NativeSocket socket, SocketProtocol protocol, bool should_close);
~Socket();

// Initialize a Tcp Socket object in listening mode. listen and accept are implemented
// separately because the caller may wish to manipulate or query the socket after it is
// initialized, but before entering a blocking accept.
static Error TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicate<uint16_t>* predicate);
static Error TcpConnect(llvm::StringRef host_and_port, Socket *&socket);
static Error UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, Socket *&recv_socket);
static Error UnixDomainConnect(llvm::StringRef host_and_port, Socket *&socket);
static Error UnixDomainAccept(llvm::StringRef host_and_port, Socket *&socket);

// Blocks on a listening socket until a connection is received. This method assumes that
// |this->m_socket| is a listening socket, created via either TcpListen() or via the native
// constructor that takes a NativeSocket, which itself was created via a call to |listen()|
Error BlockingAccept(llvm::StringRef host_and_port, Socket *&socket);

int GetOption (int level, int option_name, int &option_value);
int SetOption (int level, int option_name, int option_value);

static uint16_t GetPortNumber(const NativeSocket& socket);
uint16_t GetPortNumber () const;

NativeSocket GetNativeSocket () const { return m_socket; }
SocketProtocol GetSocketProtocol() const { return m_protocol; }

virtual Error Read (void *buf, size_t &num_bytes);
virtual Error Write (const void *buf, size_t &num_bytes);

virtual Error PreDisconnect();
virtual Error Close();

virtual bool IsValid() const { return m_socket != kInvalidSocketValue; }
virtual WaitableHandle GetWaitableHandle();

protected:
static bool
DecodeHostAndPort (llvm::StringRef host_and_port,
std::string &host_str,
std::string &port_str,
int32_t& port,
Error *error_ptr);


SocketProtocol m_protocol;
NativeSocket m_socket;
SocketAddress m_udp_send_sockaddr; // Send address used for UDP connections.
};
}

#endif
2 changes: 2 additions & 0 deletions include/lldb/lldb-forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class InlineFunctionInfo;
class Instruction;
class InstructionList;
class IOHandler;
class IOObject;
class IRExecutionUnit;
class JITLoader;
class LanguageRuntime;
Expand Down Expand Up @@ -310,6 +311,7 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
typedef std::shared_ptr<lldb_private::IOHandler> IOHandlerSP;
typedef std::shared_ptr<lldb_private::IOObject> IOObjectSP;
typedef std::shared_ptr<lldb_private::JITLoader> JITLoaderSP;
typedef std::shared_ptr<lldb_private::LanguageRuntime> LanguageRuntimeSP;
typedef std::shared_ptr<lldb_private::SystemRuntime> SystemRuntimeSP;
Expand Down
Loading

0 comments on commit d5832f8

Please sign in to comment.