[Lldb-commits] [lldb] r214984 - Creates a socket host object.
Zachary Turner
zturner at google.com
Wed Aug 6 11:16:26 PDT 2014
Author: zturner
Date: Wed Aug 6 13:16:26 2014
New Revision: 214984
URL: http://llvm.org/viewvc/llvm-project?rev=214984&view=rev
Log:
Creates a socket host object.
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
Added:
lldb/trunk/include/lldb/Host/IOObject.h
lldb/trunk/include/lldb/Host/Socket.h
lldb/trunk/source/Host/common/IOObject.cpp
lldb/trunk/source/Host/common/Socket.cpp
Modified:
lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h
lldb/trunk/include/lldb/Host/Editline.h
lldb/trunk/include/lldb/Host/File.h
lldb/trunk/include/lldb/lldb-forward.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/source/Core/ConnectionFileDescriptor.cpp
lldb/trunk/source/Host/common/CMakeLists.txt
lldb/trunk/source/Host/common/File.cpp
lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp
lldb/trunk/tools/lldb-platform/lldb-platform.cpp
Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h (original)
+++ lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h Wed Aug 6 13:16:26 2014
@@ -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 :
@@ -65,33 +63,18 @@ public:
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 ();
@@ -101,47 +84,31 @@ protected:
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);
};
Modified: lldb/trunk/include/lldb/Host/Editline.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Editline.h?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/Editline.h (original)
+++ lldb/trunk/include/lldb/Host/Editline.h Wed Aug 6 13:16:26 2014
@@ -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 {
Modified: lldb/trunk/include/lldb/Host/File.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/File.h?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/File.h (original)
+++ lldb/trunk/include/lldb/Host/File.h Wed Aug 6 13:16:26 2014
@@ -16,6 +16,7 @@
#include <sys/types.h>
#include "lldb/lldb-private.h"
+#include "lldb/Host/IOObject.h"
namespace lldb_private {
@@ -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;
@@ -48,22 +49,22 @@ public:
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)
{
@@ -118,11 +119,11 @@ public:
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)
{
}
@@ -222,6 +223,10 @@ public:
int
GetDescriptor() const;
+ WaitableHandle
+ GetWaitableHandle();
+
+
void
SetDescriptor(int fd, bool transfer_ownership);
@@ -541,7 +546,6 @@ protected:
FILE *m_stream;
uint32_t m_options;
bool m_own_stream;
- bool m_own_descriptor;
LazyBool m_is_interactive;
LazyBool m_is_real_terminal;
};
Added: lldb/trunk/include/lldb/Host/IOObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/IOObject.h?rev=214984&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Host/IOObject.h (added)
+++ lldb/trunk/include/lldb/Host/IOObject.h Wed Aug 6 13:16:26 2014
@@ -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
\ No newline at end of file
Added: lldb/trunk/include/lldb/Host/Socket.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Socket.h?rev=214984&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Host/Socket.h (added)
+++ lldb/trunk/include/lldb/Host/Socket.h Wed Aug 6 13:16:26 2014
@@ -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
\ No newline at end of file
Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Wed Aug 6 13:16:26 2014
@@ -106,6 +106,7 @@ class InlineFunctionInfo;
class Instruction;
class InstructionList;
class IOHandler;
+class IOObject;
class IRExecutionUnit;
class JITLoader;
class LanguageRuntime;
@@ -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;
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Aug 6 13:16:26 2014
@@ -67,6 +67,8 @@
232CB61E191E00CD00EF39FC /* SoftwareBreakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */; };
233B007D1960C9F90090E598 /* ProcessInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007B1960C9E60090E598 /* ProcessInfo.cpp */; };
233B007F1960CB280090E598 /* ProcessLaunchInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */; };
+ 236124A41986B4E2004EFC37 /* IoObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 236124A21986B4E2004EFC37 /* IoObject.cpp */; };
+ 236124A51986B4E2004EFC37 /* Socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 236124A31986B4E2004EFC37 /* Socket.cpp */; };
23DDF226196C3EE600BB8417 /* CommandOptionValidators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23DDF224196C3EE600BB8417 /* CommandOptionValidators.cpp */; };
23EDE33319269E7C00F6A132 /* NativeRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */; };
23EFE389193D1ABC00E54E54 /* SBTypeEnumMember.h in Headers */ = {isa = PBXBuildFile; fileRef = 23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -929,6 +931,10 @@
233B00A919622F3F0090E598 /* NativeRegisterContextLinux_x86_64.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeRegisterContextLinux_x86_64.cpp; sourceTree = "<group>"; };
233B00AA19622F3F0090E598 /* NativeRegisterContextLinux_x86_64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeRegisterContextLinux_x86_64.h; sourceTree = "<group>"; };
2360092C193FB21500189DB1 /* MemoryRegionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MemoryRegionInfo.h; path = include/lldb/Target/MemoryRegionInfo.h; sourceTree = "<group>"; };
+ 236124A21986B4E2004EFC37 /* IoObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IoObject.cpp; sourceTree = "<group>"; };
+ 236124A31986B4E2004EFC37 /* Socket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Socket.cpp; sourceTree = "<group>"; };
+ 236124A61986B50E004EFC37 /* IoObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IoObject.h; path = include/lldb/Host/IoObject.h; sourceTree = "<group>"; };
+ 236124A71986B50E004EFC37 /* Socket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Socket.h; path = include/lldb/Host/Socket.h; sourceTree = "<group>"; };
23DDF224196C3EE600BB8417 /* CommandOptionValidators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandOptionValidators.cpp; path = source/Interpreter/CommandOptionValidators.cpp; sourceTree = "<group>"; };
23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContext.cpp; path = source/Target/NativeRegisterContext.cpp; sourceTree = "<group>"; };
23EDE3311926843600F6A132 /* NativeRegisterContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContext.h; path = include/lldb/Target/NativeRegisterContext.h; sourceTree = "<group>"; };
@@ -3421,6 +3427,7 @@
260C6EA013011578005E16B0 /* File.h */,
26FA4315130103F400E71120 /* FileSpec.h */,
26BC7DD410F1B7D500F91463 /* Host.h */,
+ 236124A61986B50E004EFC37 /* IoObject.h */,
26BC7DD510F1B7D500F91463 /* Mutex.h */,
232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */,
232CB60C191E00CC00EF39FC /* NativeBreakpoint.h */,
@@ -3433,6 +3440,7 @@
A36FF33D17D8E98800244D40 /* OptionParser.h */,
260A39A519647A3A004B4130 /* Pipe.h */,
26BC7DD610F1B7D500F91463 /* Predicate.h */,
+ 236124A71986B50E004EFC37 /* Socket.h */,
26D7E45B13D5E2F9007FD12B /* SocketAddress.h */,
26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */,
232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */,
@@ -3957,9 +3965,11 @@
26FA43171301048600E71120 /* FileSpec.cpp */,
69A01E1B1236C5D400C660B5 /* Condition.cpp */,
69A01E1C1236C5D400C660B5 /* Host.cpp */,
+ 236124A21986B4E2004EFC37 /* IoObject.cpp */,
69A01E1E1236C5D400C660B5 /* Mutex.cpp */,
A36FF33B17D8E94600244D40 /* OptionParser.cpp */,
260A39A719647A4E004B4130 /* Pipe.cpp */,
+ 236124A31986B4E2004EFC37 /* Socket.cpp */,
69A01E1F1236C5D400C660B5 /* Symbols.cpp */,
268DA873130095ED00C9483A /* Terminal.cpp */,
69A01E201236C5D400C660B5 /* TimeValue.cpp */,
@@ -4696,6 +4706,7 @@
2689002913353DDE00698AC0 /* CommandObjectVersion.cpp in Sources */,
2689002A13353E0400698AC0 /* Address.cpp in Sources */,
2689002B13353E0400698AC0 /* AddressRange.cpp in Sources */,
+ 236124A41986B4E2004EFC37 /* IoObject.cpp in Sources */,
2689002C13353E0400698AC0 /* AddressResolver.cpp in Sources */,
2689002D13353E0400698AC0 /* AddressResolverFileLine.cpp in Sources */,
2689002E13353E0400698AC0 /* AddressResolverName.cpp in Sources */,
@@ -4712,6 +4723,7 @@
2689003813353E0400698AC0 /* DataExtractor.cpp in Sources */,
2689003913353E0400698AC0 /* Debugger.cpp in Sources */,
2689003A13353E0400698AC0 /* Disassembler.cpp in Sources */,
+ 236124A51986B4E2004EFC37 /* Socket.cpp in Sources */,
AF1729D7182C907200E0AB97 /* HistoryUnwind.cpp in Sources */,
2689003B13353E0400698AC0 /* EmulateInstruction.cpp in Sources */,
2689003C13353E0400698AC0 /* Error.cpp in Sources */,
Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original)
+++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Wed Aug 6 13:16:26 2014
@@ -16,7 +16,9 @@
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Host/Config.h"
+#include "lldb/Host/IOObject.h"
#include "lldb/Host/SocketAddress.h"
+#include "lldb/Host/Socket.h"
// C Includes
#include <errno.h>
@@ -24,20 +26,9 @@
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
+
#ifndef LLDB_DISABLE_POSIX
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h>
-#include <sys/un.h>
#include <termios.h>
-#include <unistd.h>
-#endif
-#ifdef _WIN32
-#include "lldb/Host/windows/windows.h"
-#include <winsock2.h>
-#include <ws2tcpip.h>
#endif
// C++ Includes
@@ -48,60 +39,23 @@
#endif
// Project includes
#include "lldb/lldb-private-log.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Log.h"
-#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/Socket.h"
+#include "lldb/Interpreter/Args.h"
using namespace lldb;
using namespace lldb_private;
-static bool
-DecodeHostAndPort (const char *host_and_port,
- std::string &host_str,
- std::string &port_str,
- int32_t& port,
- Error *error_ptr)
-{
- static RegularExpression g_regex ("([^:]+):([0-9]+)");
- RegularExpression::Match regex_match(2);
- if (g_regex.Execute (host_and_port, ®ex_match))
- {
- if (regex_match.GetMatchAtIndex (host_and_port, 1, host_str) &&
- regex_match.GetMatchAtIndex (host_and_port, 2, port_str))
- {
- port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
- if (port != INT32_MIN)
- {
- if (error_ptr)
- error_ptr->Clear();
- return true;
- }
- }
- }
- host_str.clear();
- port_str.clear();
- port = INT32_MIN;
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port);
- return false;
-}
-
ConnectionFileDescriptor::ConnectionFileDescriptor () :
Connection(),
- m_fd_send (-1),
- m_fd_recv (-1),
- m_fd_send_type (eFDTypeFile),
- m_fd_recv_type (eFDTypeFile),
- m_udp_send_sockaddr (new SocketAddress()),
- m_socket_timeout_usec (0),
m_pipe (),
m_mutex (Mutex::eMutexTypeRecursive),
- m_should_close_fd (false),
- m_shutting_down (false)
+ m_shutting_down (false),
+ m_waiting_for_accept (false)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
if (log)
@@ -111,17 +65,14 @@ ConnectionFileDescriptor::ConnectionFile
ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
Connection(),
- m_fd_send (fd),
- m_fd_recv (fd),
- m_fd_send_type (eFDTypeFile),
- m_fd_recv_type (eFDTypeFile),
- m_udp_send_sockaddr (new SocketAddress()),
- m_socket_timeout_usec(0),
m_pipe (),
m_mutex (Mutex::eMutexTypeRecursive),
- m_should_close_fd (owns_fd),
- m_shutting_down (false)
+ m_shutting_down (false),
+ m_waiting_for_accept (false)
{
+ m_write_sp.reset(new File(fd, owns_fd));
+ m_read_sp.reset(new File(fd, false));
+
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
if (log)
log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
@@ -177,7 +128,7 @@ ConnectionFileDescriptor::CloseCommandPi
bool
ConnectionFileDescriptor::IsConnected () const
{
- return m_fd_send >= 0 || m_fd_recv >= 0;
+ return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid());
}
ConnectionStatus
@@ -220,13 +171,17 @@ ConnectionFileDescriptor::Connect (const
{
return ConnectUDP (s + strlen("udp://"), error_ptr);
}
+#ifndef LLDB_DISABLE_POSIX
else if (strstr(s, "fd://") == s)
{
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat ("Protocol is not supported on non-posix hosts '%s'", s);
+ return eConnectionStatusError;
// Just passing a native file descriptor within this current process
// that is already opened (possibly from a service or other source).
s += strlen ("fd://");
bool success = false;
- m_fd_send = m_fd_recv = Args::StringToSInt32 (s, -1, 0, &success);
+ int fd = Args::StringToSInt32 (s, -1, 0, &success);
if (success)
{
@@ -235,26 +190,17 @@ ConnectionFileDescriptor::Connect (const
// get the flags from the file descriptor and making sure it
// isn't a bad fd.
errno = 0;
-#ifndef LLDB_DISABLE_POSIX
- int flags = ::fcntl (m_fd_send, F_GETFL, 0);
-#else
- int flags = -1;
-#endif
+ int flags = ::fcntl (fd, F_GETFL, 0);
if (flags == -1 || errno == EBADF)
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("stale file descriptor: %s", s);
- m_fd_send = m_fd_recv = -1;
+ m_read_sp.reset();
+ m_write_sp.reset();
return eConnectionStatusError;
}
else
{
- // Try and get a socket option from this file descriptor to
- // see if this is a socket and set m_is_socket accordingly.
- int resuse;
- bool is_socket = GetSocketOption (m_fd_send, SOL_SOCKET, SO_REUSEADDR, resuse) == 0;
- if (is_socket)
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
// Don't take ownership of a file descriptor that gets passed
// to us since someone else opened the file descriptor and
// handed it to us.
@@ -264,37 +210,55 @@ ConnectionFileDescriptor::Connect (const
// option be "owns=1" or "owns=0" or something like this to
// allow us to specify this. For now, we assume we must
// assume we don't own it.
- m_should_close_fd = false;
+
+ std::unique_ptr<Socket> tcp_socket;
+ tcp_socket.reset(new Socket(fd, Socket::ProtocolTcp, false));
+ // Try and get a socket option from this file descriptor to
+ // see if this is a socket and set m_is_socket accordingly.
+ int resuse;
+ bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse);
+ if (is_socket)
+ {
+ m_read_sp = std::move(tcp_socket);
+ m_write_sp = m_read_sp;
+ }
+ else
+ {
+ m_read_sp.reset(new File(fd, false));
+ m_write_sp.reset(new File(fd, false));
+ }
return eConnectionStatusSuccess;
}
}
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("invalid file descriptor: \"fd://%s\"", s);
- m_fd_send = m_fd_recv = -1;
+ m_read_sp.reset();
+ m_write_sp.reset();
return eConnectionStatusError;
}
else if (strstr(s, "file://") == s)
{
// file:///PATH
const char *path = s + strlen("file://");
-#ifndef LLDB_DISABLE_POSIX
+ int fd = -1;
do
{
- m_fd_send = m_fd_recv = ::open (path, O_RDWR);
- } while (m_fd_send == -1 && errno == EINTR);
- if (m_fd_send == -1)
+ fd = ::open (path, O_RDWR);
+ } while (fd == -1 && errno == EINTR);
+
+ if (fd == -1)
{
if (error_ptr)
error_ptr->SetErrorToErrno();
return eConnectionStatusError;
}
- if (::isatty(m_fd_send))
+ if (::isatty(fd))
{
// Set up serial terminal emulation
struct termios options;
- ::tcgetattr (m_fd_send, &options);
+ ::tcgetattr (fd, &options);
// Set port speed to maximum
::cfsetospeed (&options, B115200);
@@ -307,24 +271,23 @@ ConnectionFileDescriptor::Connect (const
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
- ::tcsetattr (m_fd_send, TCSANOW, &options);
+ ::tcsetattr (fd, TCSANOW, &options);
}
- int flags = ::fcntl (m_fd_send, F_GETFL, 0);
+ int flags = ::fcntl (fd, F_GETFL, 0);
if (flags >= 0)
{
if ((flags & O_NONBLOCK) == 0)
{
flags |= O_NONBLOCK;
- ::fcntl (m_fd_send, F_SETFL, flags);
+ ::fcntl (fd, F_SETFL, flags);
}
}
- m_should_close_fd = true;
+ m_read_sp.reset(new File(fd, true));
+ m_write_sp.reset(new File(fd, false));
return eConnectionStatusSuccess;
-#else
- return eConnectionStatusError;
-#endif
}
+#endif
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s);
return eConnectionStatusError;
@@ -348,12 +311,9 @@ ConnectionFileDescriptor::Disconnect (Er
log->Printf ("%p ConnectionFileDescriptor::Disconnect ()",
static_cast<void*>(this));
- // Reset the port predicate when disconnecting and don't broadcast
- m_port_predicate.SetValue(0, eBroadcastNever);
-
ConnectionStatus status = eConnectionStatusSuccess;
- if (m_fd_send < 0 && m_fd_recv < 0)
+ if (!IsConnected())
{
if (log)
log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect",
@@ -361,6 +321,9 @@ ConnectionFileDescriptor::Disconnect (Er
return eConnectionStatusSuccess;
}
+ if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
+ static_cast<Socket&>(*m_read_sp).PreDisconnect();
+
// Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely
// because somebody is doing a blocking read on our file descriptor. If that's the case,
// then send the "q" char to the command file channel so the read will wake up and the connection
@@ -382,42 +345,22 @@ ConnectionFileDescriptor::Disconnect (Er
static_cast<void*>(this), m_pipe.GetWriteFileDescriptor(), result);
}
else if (log)
+ {
log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.",
static_cast<void*>(this));
- locker.Lock (m_mutex);
- }
-
- if (m_should_close_fd == true)
- {
- if (m_fd_send == m_fd_recv)
- {
- status = Close (m_fd_send, m_fd_send_type, error_ptr);
- }
- else
- {
- // File descriptors are the different, close both if needed
- if (m_fd_send >= 0)
- status = Close (m_fd_send, m_fd_send_type, error_ptr);
- if (m_fd_recv >= 0)
- {
- ConnectionStatus recv_status = Close (m_fd_recv, m_fd_recv_type, error_ptr);
- if (status == eConnectionStatusSuccess)
- status = recv_status;
- }
}
+ locker.Lock (m_mutex);
}
- // Now set all our descriptors to invalid values.
-
- m_fd_send = m_fd_recv = -1;
-
- if (status != eConnectionStatusSuccess)
- {
- return status;
- }
+ Error error = m_read_sp->Close();
+ Error error2 = m_write_sp->Close();
+ if (error.Fail() || error2.Fail())
+ status = eConnectionStatusError;
+ if (error_ptr)
+ *error_ptr = error.Fail() ? error : error2;
m_shutting_down = false;
- return eConnectionStatusSuccess;
+ return status;
}
size_t
@@ -428,10 +371,6 @@ ConnectionFileDescriptor::Read (void *ds
Error *error_ptr)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %" PRIu64 ")...",
- static_cast<void*>(this), m_fd_recv,
- static_cast<void*>(dst), static_cast<uint64_t>(dst_len));
Mutex::Locker locker;
bool got_lock = locker.TryLock (m_mutex);
@@ -449,54 +388,30 @@ ConnectionFileDescriptor::Read (void *ds
else if (m_shutting_down)
return eConnectionStatusError;
- ssize_t bytes_read = 0;
-
status = BytesAvailable (timeout_usec, error_ptr);
- if (status == eConnectionStatusSuccess)
- {
- do
- {
-#ifndef LLDB_DISABLE_POSIX
- bytes_read = ::read (m_fd_recv, dst, dst_len);
-#else
- switch (m_fd_send_type) {
- case eFDTypeSocket:
- case eFDTypeSocketUDP:
- bytes_read = ::recv (m_fd_recv, (char*)dst, dst_len, 0);
- break;
- default:
- bytes_read = -1;
- break;
-
- }
-
-#endif
- } while (bytes_read < 0 && errno == EINTR);
- }
-
if (status != eConnectionStatusSuccess)
return 0;
Error error;
+ size_t bytes_read = dst_len;
+ error = m_read_sp->Read(dst, bytes_read);
+
+ if (log)
+ {
+ log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s",
+ static_cast<void*>(this),
+ static_cast<uint64_t>(m_read_sp->GetWaitableHandle()),
+ static_cast<void*>(dst),
+ static_cast<uint64_t>(dst_len),
+ static_cast<uint64_t>(bytes_read),
+ error.AsCString());
+ }
+
if (bytes_read == 0)
{
error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers.
status = eConnectionStatusEndOfFile;
}
- else if (bytes_read < 0)
- {
- error.SetErrorToErrno();
- }
- else
- {
- error.Clear();
- }
-
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %" PRIu64 ") => %" PRIi64 ", error = %s",
- static_cast<void*>(this), m_fd_recv,
- static_cast<void*>(dst), static_cast<uint64_t>(dst_len),
- static_cast<int64_t>(bytes_read), error.AsCString());
if (error_ptr)
*error_ptr = error;
@@ -507,7 +422,7 @@ ConnectionFileDescriptor::Read (void *ds
switch (error_value)
{
case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read.
- if (m_fd_recv_type == eFDTypeSocket || m_fd_recv_type == eFDTypeSocketUDP)
+ if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
status = eConnectionStatusTimedOut;
else
status = eConnectionStatusSuccess;
@@ -576,75 +491,18 @@ ConnectionFileDescriptor::Write (const v
Error error;
- ssize_t bytes_sent = 0;
-
- switch (m_fd_send_type)
- {
- case eFDTypeFile: // Other FD requiring read/write
-#ifndef LLDB_DISABLE_POSIX
- do
- {
- bytes_sent = ::write (m_fd_send, src, src_len);
- } while (bytes_sent < 0 && errno == EINTR);
-#endif
- break;
- case eFDTypeSocket: // Socket requiring send/recv
- do
- {
- bytes_sent = ::send (m_fd_send, (char*)src, src_len, 0);
- } while (bytes_sent < 0 && errno == EINTR);
- break;
-
- case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
- assert (m_udp_send_sockaddr->GetFamily() != 0);
- do
- {
- bytes_sent = ::sendto (m_fd_send,
- (char*)src,
- src_len,
- 0,
- *m_udp_send_sockaddr,
- m_udp_send_sockaddr->GetLength());
- } while (bytes_sent < 0 && errno == EINTR);
- break;
- }
-
- if (bytes_sent < 0)
- error.SetErrorToErrno ();
- else
- error.Clear ();
+ size_t bytes_sent = src_len;
+ error = m_write_sp->Write(src, bytes_sent);
if (log)
{
- switch (m_fd_send_type)
- {
- case eFDTypeFile: // Other FD requiring read/write
- log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %" PRIu64 ") => %" PRIi64 " (error = %s)",
- static_cast<void*>(this), m_fd_send,
- static_cast<const void*>(src),
- static_cast<uint64_t>(src_len),
- static_cast<int64_t>(bytes_sent),
- error.AsCString());
- break;
-
- case eFDTypeSocket: // Socket requiring send/recv
- log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
- static_cast<void*>(this), m_fd_send,
- static_cast<const void*>(src),
- static_cast<uint64_t>(src_len),
- static_cast<int64_t>(bytes_sent),
- error.AsCString());
- break;
-
- case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
- log->Printf ("%p ConnectionFileDescriptor::Write() ::sendto (socket = %i, src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
- static_cast<void*>(this), m_fd_send,
- static_cast<const void*>(src),
- static_cast<uint64_t>(src_len),
- static_cast<int64_t>(bytes_sent),
- error.AsCString());
- break;
- }
+ log->Printf ("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)",
+ static_cast<void*>(this),
+ static_cast<uint64_t>(m_write_sp->GetWaitableHandle()),
+ static_cast<const void*>(src),
+ static_cast<uint64_t>(src_len),
+ static_cast<uint64_t>(bytes_sent),
+ error.AsCString());
}
if (error_ptr)
@@ -704,16 +562,17 @@ ConnectionFileDescriptor::BytesAvailable
// Don't need to take the mutex here separately since we are only called from Read. If we
// ever get used more generally we will need to lock here as well.
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_CONNECTION));
if (log)
log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)",
static_cast<void*>(this), timeout_usec);
+
struct timeval *tv_ptr;
struct timeval tv;
if (timeout_usec == UINT32_MAX)
{
- // Infinite wait...
- tv_ptr = NULL;
+ // Inifinite wait...
+ tv_ptr = nullptr;
}
else
{
@@ -727,21 +586,20 @@ ConnectionFileDescriptor::BytesAvailable
// Make a copy of the file descriptors to make sure we don't
// have another thread change these values out from under us
// and cause problems in the loop below where like in FS_SET()
- const int data_fd = m_fd_recv;
+ const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle();
const int pipe_fd = m_pipe.GetReadFileDescriptor();
- if (data_fd >= 0)
+ if (handle != IOObject::kInvalidHandleValue)
{
const bool have_pipe_fd = pipe_fd >= 0;
#if !defined(__APPLE__) && !defined(_MSC_VER)
- assert (data_fd < FD_SETSIZE);
+ assert (handle < FD_SETSIZE);
if (have_pipe_fd)
assert (pipe_fd < FD_SETSIZE);
#endif
-
- while (data_fd == m_fd_recv)
+ while (handle == m_read_sp->GetWaitableHandle())
{
- const int nfds = std::max<int>(data_fd, pipe_fd) + 1;
+ const int nfds = std::max<int>(handle, pipe_fd) + 1;
#if defined(__APPLE__)
llvm::SmallVector<fd_set, 1> read_fds;
read_fds.resize((nfds/FD_SETSIZE) + 1);
@@ -754,7 +612,7 @@ ConnectionFileDescriptor::BytesAvailable
fd_set read_fds;
FD_ZERO (&read_fds);
#endif
- FD_SET (data_fd, FD_SET_DATA(read_fds));
+ FD_SET (handle, FD_SET_DATA(read_fds));
if (have_pipe_fd)
FD_SET (pipe_fd, FD_SET_DATA(read_fds));
@@ -764,11 +622,11 @@ ConnectionFileDescriptor::BytesAvailable
{
if (have_pipe_fd)
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p)...",
- static_cast<void*>(this), nfds, data_fd, pipe_fd,
+ static_cast<void*>(this), nfds, handle, pipe_fd,
static_cast<void*>(tv_ptr));
else
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...",
- static_cast<void*>(this), nfds, data_fd,
+ static_cast<void*>(this), nfds, handle,
static_cast<void*>(tv_ptr));
}
@@ -782,12 +640,12 @@ ConnectionFileDescriptor::BytesAvailable
{
if (have_pipe_fd)
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p) => %d, error = %s",
- static_cast<void*>(this), nfds, data_fd,
+ static_cast<void*>(this), nfds, handle,
pipe_fd, static_cast<void*>(tv_ptr), num_set_fds,
error.AsCString());
else
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p) => %d, error = %s",
- static_cast<void*>(this), nfds, data_fd,
+ static_cast<void*>(this), nfds, handle,
static_cast<void*>(tv_ptr), num_set_fds,
error.AsCString());
}
@@ -821,7 +679,7 @@ ConnectionFileDescriptor::BytesAvailable
}
else if (num_set_fds > 0)
{
- if (FD_ISSET(data_fd, FD_SET_DATA(read_fds)))
+ if (FD_ISSET(handle, FD_SET_DATA(read_fds)))
return eConnectionStatusSuccess;
if (have_pipe_fd && FD_ISSET(pipe_fd, FD_SET_DATA(read_fds)))
{
@@ -855,717 +713,87 @@ ConnectionFileDescriptor::BytesAvailable
error_ptr->SetErrorString("not connected");
return eConnectionStatusLostConnection;
}
-#if 0
-#include <poll.h>
-
-// This ConnectionFileDescriptor::BytesAvailable() uses poll(). poll() should NOT
-// be used on MacOSX as it has all sorts of restrictions on the types of file descriptors
-// that it doesn't support.
-//
-// There may be some systems that properly support poll() that could use this
-// implementation. I will let each system opt into this on their own.
-//
-// PROS:
-// - no restrictions on the fd value that is used
-// CONS:
-// - varies wildly from platform to platform in its implementation restrictions
ConnectionStatus
-ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
+ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr)
{
- // Don't need to take the mutex here separately since we are only called from Read. If we
- // ever get used more generally we will need to lock here as well.
-
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
- int timeout_msec = 0;
- if (timeout_usec == UINT32_MAX)
- {
- // Infinite wait...
- timeout_msec = -1;
- }
- else if (timeout_usec == 0)
- {
- // Return immediately, don't wait
- timeout_msec = 0;
- }
- else
- {
- // Convert usec to msec
- timeout_msec = (timeout_usec + 999) / 1000;
- }
-
- // Make a copy of the file descriptors to make sure we don't
- // have another thread change these values out from under us
- // and cause problems in the loop below where like in FS_SET()
- const int data_fd = m_fd_recv;
- const int pipe_fd = m_pipe.GetReadFileDescriptor();
-
- // Make sure the file descriptor can be used with select as it
- // must be in range
- if (data_fd >= 0)
- {
- const bool have_pipe_fd = pipe_fd >= 0;
- struct pollfd fds[2] =
- {
- { data_fd, POLLIN, 0 },
- { pipe_fd, POLLIN, 0 }
- };
- const int nfds = have_pipe_fd ? 2 : 1;
- Error error;
- while (data_fd == m_fd_recv)
- {
- const int num_set_fds = ::poll (fds, nfds, timeout_msec);
-
- if (num_set_fds < 0)
- error.SetErrorToErrno();
- else
- error.Clear();
-
- if (error_ptr)
- *error_ptr = error;
-
- if (log)
- {
- if (have_pipe_fd)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::poll (fds={{%i,POLLIN},{%i,POLLIN}}, nfds=%i, timeout_ms=%i) => %d, error = %s\n",
- this,
- data_fd,
- pipe_fd,
- nfds,
- timeout_msec,
- num_set_fds,
- error.AsCString());
- else
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::poll (fds={{%i,POLLIN}}, nfds=%i, timeout_ms=%i) => %d, error = %s\n",
- this,
- data_fd,
- nfds,
- timeout_msec,
- num_set_fds,
- error.AsCString());
- }
-
- if (error.Fail())
- {
- switch (error.GetError())
- {
- case EBADF: // One of the descriptor sets specified an invalid descriptor.
- return eConnectionStatusLostConnection;
-
- case EINVAL: // The specified time limit is invalid. One of its components is negative or too large.
- default: // Other unknown error
- return eConnectionStatusError;
-
- case EAGAIN: // The kernel was (perhaps temporarily) unable to
- // allocate the requested number of file descriptors,
- // or we have non-blocking IO
- case EINTR: // A signal was delivered before the time limit
- // expired and before any of the selected events
- // occurred.
- break; // Lets keep reading to until we timeout
- }
- }
- else if (num_set_fds == 0)
- {
- return eConnectionStatusTimedOut;
- }
- else if (num_set_fds > 0)
- {
- if (fds[0].revents & POLLIN)
- return eConnectionStatusSuccess;
- if (fds[1].revents & POLLIN)
- {
- // We got a command to exit. Read the data from that pipe:
- char buffer[16];
- ssize_t bytes_read;
-
- do
- {
- bytes_read = ::read (pipe_fd, buffer, sizeof(buffer));
- } while (bytes_read < 0 && errno == EINTR);
-
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
- static_cast<void*>(this),
- static_cast<int>(bytes_read), buffer);
-
- return eConnectionStatusEndOfFile;
- }
- }
- }
- }
+ Socket* socket = nullptr;
+ Error error = Socket::UnixDomainAccept(socket_name, socket);
if (error_ptr)
- error_ptr->SetErrorString("not connected");
- return eConnectionStatusLostConnection;
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError;
}
-#endif
-
ConnectionStatus
-ConnectionFileDescriptor::Close (int& fd, FDType type, Error *error_ptr)
+ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *error_ptr)
{
+ Socket* socket = nullptr;
+ Error error = Socket::UnixDomainConnect(socket_name, socket);
if (error_ptr)
- error_ptr->Clear();
- bool success = true;
- // Avoid taking a lock if we can
- if (fd >= 0)
- {
- Mutex::Locker locker (m_mutex);
- // Check the FD after the lock is taken to ensure only one thread
- // can get into the close scope below
- if (fd >= 0)
- {
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::Close (fd = %i)",
- static_cast<void*>(this), fd);
-#if _WIN32
- if (type != eFDTypeFile)
- success = closesocket(fd) == 0;
- else
-#endif
- success = ::close (fd) == 0;
- // A reference to a FD was passed in, set it to an invalid value
- fd = -1;
- if (!success && error_ptr)
- {
- // Only set the error if we have been asked to since something else
- // might have caused us to try and shut down the connection and may
- // have already set the error.
- error_ptr->SetErrorToErrno();
- }
- }
- }
- if (success)
- return eConnectionStatusSuccess;
- else
- return eConnectionStatusError;
-}
-
-ConnectionStatus
-ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr)
-{
-#ifndef LLDB_DISABLE_POSIX
- ConnectionStatus result = eConnectionStatusError;
- struct sockaddr_un saddr_un;
-
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
-
- int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0);
- if (listen_socket == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- return eConnectionStatusError;
- }
-
- saddr_un.sun_family = AF_UNIX;
- ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1);
- saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
- saddr_un.sun_len = SUN_LEN (&saddr_un);
-#endif
-
- Host::Unlink (socket_name);
- if (::bind (listen_socket, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
- {
- if (::listen (listen_socket, 5) == 0)
- {
- m_fd_send = m_fd_recv = ::accept (listen_socket, NULL, 0);
- if (m_fd_send > 0)
- {
- m_should_close_fd = true;
-
- if (error_ptr)
- error_ptr->Clear();
- result = eConnectionStatusSuccess;
- }
- }
- }
-
- if (result != eConnectionStatusSuccess)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- }
- // We are done with the listen port
- Close (listen_socket, eFDTypeSocket, NULL);
- return result;
-#else
- return eConnectionStatusError;
-#endif
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError;
}
ConnectionStatus
-ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *error_ptr)
+ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr)
{
-#ifndef LLDB_DISABLE_POSIX
- Disconnect (NULL);
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
+ m_port_predicate.SetValue(0, eBroadcastNever);
- // Open the socket that was passed in as an option
- struct sockaddr_un saddr_un;
- m_fd_send = m_fd_recv = ::socket (AF_UNIX, SOCK_STREAM, 0);
- if (m_fd_send == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
+ Socket* socket = nullptr;
+ m_waiting_for_accept = true;
+ Error error = Socket::TcpListen(s, socket, &m_port_predicate);
+ if (error_ptr)
+ *error_ptr = error;
+ if (error.Fail())
return eConnectionStatusError;
- }
- saddr_un.sun_family = AF_UNIX;
- ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1);
- saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
- saddr_un.sun_len = SUN_LEN (&saddr_un);
-#endif
+ std::unique_ptr<Socket> listening_socket_up;
- if (::connect (m_fd_send, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Disconnect (NULL);
- return eConnectionStatusError;
- }
+ listening_socket_up.reset(socket);
+ socket = nullptr;
+ error = listening_socket_up->BlockingAccept(s, socket);
+ listening_socket_up.reset();
if (error_ptr)
- error_ptr->Clear();
- return eConnectionStatusSuccess;
-#else
- return eConnectionStatusError;
-#endif
-}
-
-ConnectionStatus
-ConnectionFileDescriptor::SocketListen (const char *host_and_port, Error *error_ptr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::SocketListen (%s)",
- static_cast<void*>(this), host_and_port);
-
- Disconnect (NULL);
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
- std::string host_str;
- std::string port_str;
- int32_t port = INT32_MIN;
- if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr))
- {
- // Might be just a port number
- port = Args::StringToSInt32(host_and_port, -1);
- if (port == -1)
- return eConnectionStatusError;
- else
- host_str.clear();
- }
- const sa_family_t family = AF_INET;
- const int socktype = SOCK_STREAM;
- const int protocol = IPPROTO_TCP;
- int listen_fd = ::socket (family, socktype, protocol);
- if (listen_fd == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
+ *error_ptr = error;
+ if (error.Fail())
return eConnectionStatusError;
- }
-
- // enable local address reuse
- SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1);
-
- 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))
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
- Close (listen_fd, eFDTypeSocket, NULL);
- return eConnectionStatusError;
- }
- }
- SocketAddress anyaddr;
- if (anyaddr.SetToAnyAddress (family, port))
- {
- int err = ::bind (listen_fd, anyaddr, anyaddr.GetLength());
- if (err == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Close (listen_fd, eFDTypeSocket, NULL);
- return eConnectionStatusError;
- }
-
- err = ::listen (listen_fd, 1);
- if (err == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Close (listen_fd, eFDTypeSocket, NULL);
- return eConnectionStatusError;
- }
-
- // 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 = GetSocketPort(listen_fd);
-
- // 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.
- m_port_predicate.SetValue(port, eBroadcastAlways);
-
-
- bool accept_connection = false;
-
- // 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 fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len);
-
- if (fd == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- break;
- }
-
- if (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)
- {
- accept_connection = true;
- m_fd_send = m_fd_recv = fd;
- }
- else
- {
- if (
-#if !(defined(__linux__) || (defined(_WIN32)))
- accept_addr_len == listen_addr.sockaddr_in().sin_len &&
-#endif
- accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr)
- {
- accept_connection = true;
- m_fd_send = m_fd_recv = fd;
- }
- else
- {
- ::close (fd);
- m_fd_send = m_fd_recv = -1;
- 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]);
- }
- }
- }
-
- if (m_fd_send == -1)
- {
- Close (listen_fd, eFDTypeSocket, NULL);
- return eConnectionStatusError;
- }
- }
-
- // We are done with the listen port
- Close (listen_fd, eFDTypeSocket, NULL);
-
- m_should_close_fd = true;
-
- // Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd_send, IPPROTO_TCP, TCP_NODELAY, 1);
- if (error_ptr)
- error_ptr->Clear();
- return eConnectionStatusSuccess;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError;
}
ConnectionStatus
-ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_ptr)
+ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr)
{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)",
- static_cast<void*>(this), host_and_port);
- Disconnect (NULL);
-
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
- std::string host_str;
- std::string port_str;
- int32_t port = INT32_MIN;
- if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr))
- return eConnectionStatusError;
-
- // Create the socket
- m_fd_send = m_fd_recv = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (m_fd_send == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- return eConnectionStatusError;
- }
-
- m_should_close_fd = true;
-
- // Enable local address reuse
- SetSocketOption (m_fd_send, SOL_SOCKET, SO_REUSEADDR, 1);
-
- struct sockaddr_in sa;
- ::memset (&sa, 0, sizeof (sa));
- sa.sin_family = AF_INET;
- sa.sin_port = htons (port);
-
- int inet_pton_result = ::inet_pton (AF_INET, 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 (AF_INET, host_str.c_str(), &sa.sin_addr);
- if (inet_pton_result <= 0)
- {
-
- if (error_ptr)
- {
- if (inet_pton_result == -1)
- error_ptr->SetErrorToErrno();
- else
- error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
- }
- Disconnect (NULL);
-
- return eConnectionStatusError;
- }
- }
-
- if (-1 == ::connect (m_fd_send, (const struct sockaddr *)&sa, sizeof(sa)))
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Disconnect (NULL);
-
- return eConnectionStatusError;
- }
-
- // Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd_send, IPPROTO_TCP, TCP_NODELAY, 1);
+ Socket* socket = nullptr;
+ Error error = Socket::TcpConnect(s, socket);
if (error_ptr)
- error_ptr->Clear();
- return eConnectionStatusSuccess;
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError;
}
ConnectionStatus
-ConnectionFileDescriptor::ConnectUDP (const char *host_and_port, Error *error_ptr)
+ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr)
{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)",
- static_cast<void*>(this), host_and_port);
- Disconnect (NULL);
-
- m_fd_send_type = m_fd_recv_type = eFDTypeSocketUDP;
-
- std::string host_str;
- std::string port_str;
- int32_t port = INT32_MIN;
- if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr))
- return eConnectionStatusError;
-
- // 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.
- m_fd_recv = ::socket (AF_INET, SOCK_DGRAM, 0);
- if (m_fd_recv == -1)
- {
- // Socket creation failed...
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- }
- else
- {
- // Socket was created, now lets bind to the requested port
- SocketAddress addr;
- addr.SetToAnyAddress (AF_INET, 0);
-
- if (::bind (m_fd_recv, addr, addr.GetLength()) == -1)
- {
- // Bind failed...
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Disconnect (NULL);
- }
- }
-
- if (m_fd_recv == -1)
- return eConnectionStatusError;
-
- // 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 = NULL;
-
- ::memset (&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list);
- if (err != 0)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)",
- host_str.c_str(),
- port_str.c_str(),
- err,
- gai_strerror(err));
- Disconnect (NULL);
- return eConnectionStatusError;
- }
-
- for (struct addrinfo *service_info_ptr = service_info_list;
- service_info_ptr != NULL;
- service_info_ptr = service_info_ptr->ai_next)
- {
- m_fd_send = ::socket (service_info_ptr->ai_family,
- service_info_ptr->ai_socktype,
- service_info_ptr->ai_protocol);
-
- if (m_fd_send != -1)
- {
- *m_udp_send_sockaddr = service_info_ptr;
- break;
- }
- else
- continue;
- }
-
- :: freeaddrinfo (service_info_list);
-
- if (m_fd_send == -1)
- {
- Disconnect (NULL);
- return eConnectionStatusError;
- }
-
+ Socket* send_socket = nullptr;
+ Socket* recv_socket = nullptr;
+ Error error = Socket::UdpConnect(s, send_socket, recv_socket);
if (error_ptr)
- error_ptr->Clear();
-
- m_should_close_fd = true;
- return eConnectionStatusSuccess;
-}
-
-#if defined(_WIN32)
-typedef const char * set_socket_option_arg_type;
-typedef char * get_socket_option_arg_type;
-#else // #if defined(_WIN32)
-typedef const void * set_socket_option_arg_type;
-typedef void * get_socket_option_arg_type;
-#endif // #if defined(_WIN32)
-
-int
-ConnectionFileDescriptor::GetSocketOption(int fd, int level, int option_name, int &option_value)
-{
- get_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
- socklen_t option_value_size = sizeof(int);
- return ::getsockopt(fd, level, option_name, option_value_p, &option_value_size);
-}
-
-int
-ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, int option_value)
-{
- set_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
- return ::setsockopt(fd, level, option_name, option_value_p, sizeof(option_value));
-}
-
-bool
-ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec)
-{
- switch (m_fd_recv_type)
- {
- case eFDTypeFile: // Other FD requiring read/write
- break;
-
- case eFDTypeSocket: // Socket requiring send/recv
- case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
- {
- // Check in case timeout for m_fd has already been set to this value
- if (timeout_usec == m_socket_timeout_usec)
- return true;
- //printf ("ConnectionFileDescriptor::SetSocketReceiveTimeout (timeout_usec = %u)\n", timeout_usec);
-
- struct timeval timeout;
- if (timeout_usec == UINT32_MAX)
- {
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- }
- else if (timeout_usec == 0)
- {
- // Sending in zero does an infinite timeout, so set this as low
- // as we can go to get an effective zero timeout...
- timeout.tv_sec = 0;
- timeout.tv_usec = 1;
- }
- else
- {
- timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec;
- timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec;
- }
- if (::setsockopt (m_fd_recv, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<get_socket_option_arg_type>(&timeout), sizeof(timeout)) == 0)
- {
- m_socket_timeout_usec = timeout_usec;
- return true;
- }
- }
- }
- return false;
-}
-
-uint16_t
-ConnectionFileDescriptor::GetSocketPort (int fd)
-{
- // We bound to port zero, so we need to figure out which port we actually bound to
- if (fd >= 0)
- {
- SocketAddress sock_addr;
- socklen_t sock_addr_len = sock_addr.GetMaxLength ();
- if (::getsockname (fd, sock_addr, &sock_addr_len) == 0)
- return sock_addr.GetPort ();
- }
- return 0;
-}
-
-// If the read file descriptor is a socket, then return
-// the port number that is being used by the socket.
-uint16_t
-ConnectionFileDescriptor::GetReadPort () const
-{
- return ConnectionFileDescriptor::GetSocketPort (m_fd_recv);
+ *error_ptr = error;
+ m_write_sp.reset(send_socket);
+ m_read_sp.reset(recv_socket);
+ return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError;
}
-// If the write file descriptor is a socket, then return
-// the port number that is being used by the socket.
-uint16_t
-ConnectionFileDescriptor::GetWritePort () const
-{
- return ConnectionFileDescriptor::GetSocketPort (m_fd_send);
-}
-uint16_t
-ConnectionFileDescriptor::GetBoundPort (uint32_t timeout_sec)
+uint16_t ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec)
{
uint16_t bound_port = 0;
if (timeout_sec == UINT32_MAX)
Modified: lldb/trunk/source/Host/common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/CMakeLists.txt?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/CMakeLists.txt (original)
+++ lldb/trunk/source/Host/common/CMakeLists.txt Wed Aug 6 13:16:26 2014
@@ -7,6 +7,7 @@ add_lldb_library(lldbHostCommon
File.cpp
FileSpec.cpp
Host.cpp
+ IOObject.cpp
Mutex.cpp
NativeBreakpoint.cpp
NativeBreakpointList.cpp
@@ -15,6 +16,7 @@ add_lldb_library(lldbHostCommon
OptionParser.cpp
Pipe.cpp
ProcessRunLock.cpp
+ Socket.cpp
SocketAddress.cpp
SoftwareBreakpoint.cpp
Symbols.cpp
Modified: lldb/trunk/source/Host/common/File.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/File.cpp?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/File.cpp (original)
+++ lldb/trunk/source/Host/common/File.cpp Wed Aug 6 13:16:26 2014
@@ -24,6 +24,7 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSpec.h"
@@ -77,11 +78,11 @@ int File::kInvalidDescriptor = -1;
FILE * File::kInvalidStream = NULL;
File::File(const char *path, uint32_t options, uint32_t permissions) :
+ IOObject(eFDTypeFile, false),
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
m_options (),
m_own_stream (false),
- m_own_descriptor (false),
m_is_interactive (eLazyBoolCalculate),
m_is_real_terminal (eLazyBoolCalculate)
{
@@ -91,11 +92,11 @@ File::File(const char *path, uint32_t op
File::File (const FileSpec& filespec,
uint32_t options,
uint32_t permissions) :
+ 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)
@@ -107,11 +108,11 @@ File::File (const FileSpec& filespec,
}
File::File (const File &rhs) :
+ 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)
{
@@ -148,13 +149,20 @@ File::GetDescriptor() const
return kInvalidDescriptor;
}
+IOObject::WaitableHandle
+File::GetWaitableHandle()
+{
+ return m_descriptor;
+}
+
+
void
File::SetDescriptor (int fd, bool transfer_ownership)
{
if (IsValid())
Close();
m_descriptor = fd;
- m_own_descriptor = transfer_ownership;
+ m_should_close_fd = transfer_ownership;
}
@@ -168,7 +176,7 @@ File::GetStream ()
const char *mode = GetStreamOpenModeFromOptions (m_options);
if (mode)
{
- if (!m_own_descriptor)
+ if (!m_should_close_fd)
{
// We must duplicate the file descriptor if we don't own it because
// when you call fdopen, the stream will own the fd
@@ -177,7 +185,7 @@ File::GetStream ()
#else
m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
#endif
- m_own_descriptor = true;
+ m_should_close_fd = true;
}
do
@@ -191,7 +199,7 @@ File::GetStream ()
if (m_stream)
{
m_own_stream = true;
- m_own_descriptor = false;
+ m_should_close_fd = false;
}
}
}
@@ -228,7 +236,7 @@ File::Duplicate (const File &rhs)
else
{
m_options = rhs.m_options;
- m_own_descriptor = true;
+ m_should_close_fd = true;
}
}
else
@@ -307,7 +315,7 @@ File::Open (const char *path, uint32_t o
error.SetErrorToErrno();
else
{
- m_own_descriptor = true;
+ m_should_close_fd = true;
m_options = options;
}
@@ -371,7 +379,7 @@ File::Close ()
error.SetErrorToErrno();
}
- if (DescriptorIsValid() && m_own_descriptor)
+ if (DescriptorIsValid() && m_should_close_fd)
{
if (::close (m_descriptor) != 0)
error.SetErrorToErrno();
@@ -380,7 +388,7 @@ File::Close ()
m_stream = kInvalidStream;
m_options = 0;
m_own_stream = false;
- m_own_descriptor = false;
+ m_should_close_fd = false;
m_is_interactive = eLazyBoolCalculate;
m_is_real_terminal = eLazyBoolCalculate;
return error;
@@ -669,6 +677,7 @@ File::Write (const void *buf, size_t &nu
num_bytes = 0;
error.SetErrorString("invalid file handle");
}
+
return error;
}
Added: lldb/trunk/source/Host/common/IOObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/IOObject.cpp?rev=214984&view=auto
==============================================================================
--- lldb/trunk/source/Host/common/IOObject.cpp (added)
+++ lldb/trunk/source/Host/common/IOObject.cpp Wed Aug 6 13:16:26 2014
@@ -0,0 +1,14 @@
+//===-- IOObject.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/IOObject.h"
+
+using namespace lldb_private;
+
+const IOObject::WaitableHandle IOObject::kInvalidHandleValue = -1;
Added: lldb/trunk/source/Host/common/Socket.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Socket.cpp?rev=214984&view=auto
==============================================================================
--- lldb/trunk/source/Host/common/Socket.cpp (added)
+++ lldb/trunk/source/Host/common/Socket.cpp Wed Aug 6 13:16:26 2014
@@ -0,0 +1,661 @@
+//===-- Socket.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/Socket.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Host/Config.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/SocketAddress.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Interpreter/Args.h"
+
+#ifndef LLDB_DISABLE_POSIX
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+#if defined(_WIN32)
+typedef const char * set_socket_option_arg_type;
+typedef char * get_socket_option_arg_type;
+const NativeSocket Socket::kInvalidSocketValue = INVALID_SOCKET;
+#else // #if defined(_WIN32)
+typedef const void * set_socket_option_arg_type;
+typedef void * get_socket_option_arg_type;
+const NativeSocket Socket::kInvalidSocketValue = -1;
+#endif // #if defined(_WIN32)
+
+Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close)
+ : IOObject(eFDTypeSocket, should_close)
+ , m_protocol(protocol)
+ , m_socket(socket)
+{
+
+}
+
+Socket::~Socket()
+{
+ Close();
+}
+
+Error Socket::TcpConnect(llvm::StringRef host_and_port, Socket *&socket)
+{
+ // Store the result in a unique_ptr in case we error out, the memory will get correctly freed.
+ std::unique_ptr<Socket> final_socket;
+ NativeSocket sock = kInvalidSocketValue;
+ Error error;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
+ if (log)
+ log->Printf ("Socket::TcpConnect (host/port = %s)", host_and_port.data());
+
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
+ return error;
+
+ // Create the socket
+ sock = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock == kInvalidSocketValue)
+ {
+ // TODO: On Windows, use WSAGetLastError().
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ // Since they both refer to the same socket descriptor, arbitrarily choose the send socket to
+ // be the owner.
+ final_socket.reset(new Socket(sock, ProtocolTcp, true));
+
+ // Enable local address reuse
+ final_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
+
+ struct sockaddr_in sa;
+ ::memset (&sa, 0, sizeof (sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (port);
+
+ int inet_pton_result = ::inet_pton (AF_INET, 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 (AF_INET, host_str.c_str(), &sa.sin_addr);
+ if (inet_pton_result <= 0)
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ if (inet_pton_result == -1)
+ error.SetErrorToErrno();
+ else
+ error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
+
+ return error;
+ }
+ }
+
+ if (-1 == ::connect (sock, (const struct sockaddr *)&sa, sizeof(sa)))
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ // Keep our TCP packets coming without any delays.
+ final_socket->SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
+ error.Clear();
+ socket = final_socket.release();
+ return error;
+}
+
+Error Socket::TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicate<uint16_t>* predicate)
+{
+ std::unique_ptr<Socket> listen_socket;
+ NativeSocket listen_sock = kInvalidSocketValue;
+ Error error;
+
+ const sa_family_t family = AF_INET;
+ const int socktype = SOCK_STREAM;
+ const int protocol = IPPROTO_TCP;
+ listen_sock = ::socket (family, socktype, protocol);
+ if (listen_sock == kInvalidSocketValue)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ listen_socket.reset(new Socket(listen_sock, ProtocolTcp, true));
+
+ // enable local address reuse
+ listen_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("ConnectionFileDescriptor::SocketListen (%s)", host_and_port.data());
+
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
+ return error;
+
+ SocketAddress anyaddr;
+ if (anyaddr.SetToAnyAddress (family, port))
+ {
+ int err = ::bind (listen_sock, anyaddr, anyaddr.GetLength());
+ if (err == -1)
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ err = ::listen (listen_sock, 1);
+ if (err == -1)
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ // 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->GetPortNumber();
+
+ // 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();
+ }
+
+ return error;
+}
+
+Error Socket::BlockingAccept(llvm::StringRef host_and_port, Socket *&socket)
+{
+ Error error;
+ std::string host_str;
+ std::string port_str;
+ int32_t port;
+ if (!DecodeHostAndPort(host_and_port, host_str, port_str, port, &error))
+ return error;
+
+ const sa_family_t family = AF_INET;
+ const int socktype = SOCK_STREAM;
+ 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<Socket> 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 = ::accept (this->GetNativeSocket(), (struct sockaddr *)&accept_addr, &accept_addr_len);
+
+ if (sock == kInvalidSocketValue)
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ error.SetErrorToErrno();
+ 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;
+ // Since both sockets have the same descriptor, arbitrarily choose the send
+ // socket to be the owner.
+ accepted_socket.reset(new Socket(sock, ProtocolTcp, 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->SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
+ error.Clear();
+ socket = accepted_socket.release();
+ return error;
+
+}
+
+Error Socket::UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, Socket *&recv_socket)
+{
+ std::unique_ptr<Socket> final_send_socket;
+ std::unique_ptr<Socket> final_recv_socket;
+ NativeSocket final_send_fd = kInvalidSocketValue;
+ NativeSocket final_recv_fd = kInvalidSocketValue;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("Socket::UdpConnect (host/port = %s)", host_and_port.data());
+
+ Error error;
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (host_and_port, 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_fd = ::socket (AF_INET, SOCK_DGRAM, 0);
+ if (final_recv_fd == kInvalidSocketValue)
+ {
+ // Socket creation failed...
+ // TODO: On Windows, use WSAGetLastError().
+ error.SetErrorToErrno();
+ }
+ else
+ {
+ final_recv_socket.reset(new Socket(final_recv_fd, ProtocolUdp, true));
+
+ // Socket was created, now lets bind to the requested port
+ SocketAddress addr;
+ addr.SetToAnyAddress (AF_INET, 0);
+
+ if (::bind (final_recv_fd, addr, addr.GetLength()) == -1)
+ {
+ // Bind failed...
+ // TODO: On Windows use WSAGetLastError()
+ error.SetErrorToErrno();
+ }
+ }
+
+ 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 = NULL;
+
+ ::memset (&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ 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 != NULL;
+ service_info_ptr = service_info_ptr->ai_next)
+ {
+ final_send_fd = ::socket (service_info_ptr->ai_family,
+ service_info_ptr->ai_socktype,
+ service_info_ptr->ai_protocol);
+
+ if (final_send_fd != kInvalidSocketValue)
+ {
+ final_send_socket.reset(new Socket(final_send_fd, ProtocolUdp, true));
+ final_send_socket->m_udp_send_sockaddr = service_info_ptr;
+ break;
+ }
+ else
+ continue;
+ }
+
+ :: freeaddrinfo (service_info_list);
+
+ if (final_send_fd == kInvalidSocketValue)
+ {
+ // TODO: On Windows, use WSAGetLastError().
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ send_socket = final_send_socket.release();
+ recv_socket = final_recv_socket.release();
+ error.Clear();
+ return error;
+}
+
+Error Socket::UnixDomainConnect(llvm::StringRef name, Socket *&socket)
+{
+ Error error;
+#ifndef LLDB_DISABLE_POSIX
+ std::unique_ptr<Socket> final_socket;
+
+ // Open the socket that was passed in as an option
+ struct sockaddr_un saddr_un;
+ int fd = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (fd == kInvalidSocketValue)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ final_socket.reset(new Socket(fd, ProtocolUnixDomain, true));
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+#endif
+
+ if (::connect (fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ socket = final_socket.release();
+#else
+ error.SetErrorString("Unix domain sockets are not supported on this platform.");
+#endif
+ return error;
+}
+
+Error Socket::UnixDomainAccept(llvm::StringRef name, Socket *&socket)
+{
+ Error error;
+#ifndef LLDB_DISABLE_POSIX
+ struct sockaddr_un saddr_un;
+ std::unique_ptr<Socket> listen_socket;
+ std::unique_ptr<Socket> final_socket;
+ NativeSocket listen_fd = kInvalidSocketValue;
+ NativeSocket socket_fd = kInvalidSocketValue;
+
+ listen_fd = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (listen_fd == kInvalidSocketValue)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ listen_socket.reset(new Socket(listen_fd, ProtocolUnixDomain, true));
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+#endif
+
+ Host::Unlink (name.data());
+ bool success = false;
+ if (::bind (listen_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
+ {
+ if (::listen (listen_fd, 5) == 0)
+ {
+ socket_fd = ::accept (listen_fd, NULL, 0);
+ if (socket_fd > 0)
+ {
+ final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true));
+ success = true;
+ }
+ }
+ }
+
+ if (!success)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+ // We are done with the listen port
+ listen_socket.reset();
+
+ socket = final_socket.release();
+#else
+ error.SetErrorString("Unix domain sockets are not supported on this platform.");
+#endif
+ return error;
+}
+
+bool
+Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
+ std::string &host_str,
+ std::string &port_str,
+ int32_t& port,
+ Error *error_ptr)
+{
+ static RegularExpression g_regex ("([^:]+):([0-9]+)");
+ RegularExpression::Match regex_match(2);
+ if (g_regex.Execute (host_and_port.data(), ®ex_match))
+ {
+ if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) &&
+ regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str))
+ {
+ port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
+ if (port != INT32_MIN)
+ {
+ if (error_ptr)
+ error_ptr->Clear();
+ return true;
+ }
+ }
+ }
+
+ // If this was unsuccessful, then check if it's simply a signed 32-bit integer, representing
+ // a port with an empty host.
+ host_str.clear();
+ port_str.clear();
+ port = Args::StringToSInt32(host_and_port.data(), INT32_MIN);
+ if (port != INT32_MIN)
+ {
+ port_str = host_and_port;
+ return true;
+ }
+
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data());
+ return false;
+}
+
+IOObject::WaitableHandle Socket::GetWaitableHandle()
+{
+ // TODO: On Windows, use WSAEventSelect
+ return m_socket;
+}
+
+Error Socket::Read (void *buf, size_t &num_bytes)
+{
+ Error error;
+ int bytes_received = 0;
+ do
+ {
+ bytes_received = ::recv (m_socket, static_cast<char *>(buf), num_bytes, 0);
+ // TODO: Use WSAGetLastError on windows.
+ } while (bytes_received < 0 && errno == EINTR);
+
+ if (bytes_received < 0)
+ {
+ error.SetErrorToErrno();
+ num_bytes = 0;
+ }
+ else
+ num_bytes = bytes_received;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_COMMUNICATION));
+ if (log)
+ {
+ log->Printf ("%p Socket::Read() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
+ static_cast<void*>(this),
+ static_cast<uint64_t>(m_socket),
+ buf,
+ static_cast<uint64_t>(num_bytes),
+ static_cast<int64_t>(bytes_received),
+ error.AsCString());
+ }
+
+ return error;
+}
+
+Error Socket::Write (const void *buf, size_t &num_bytes)
+{
+ Error error;
+ int bytes_sent = 0;
+ do
+ {
+ if (m_protocol == ProtocolUdp)
+ {
+ bytes_sent = ::sendto (m_socket,
+ static_cast<const char*>(buf),
+ num_bytes,
+ 0,
+ m_udp_send_sockaddr,
+ m_udp_send_sockaddr.GetLength());
+ }
+ else
+ bytes_sent = ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0);
+ // TODO: Use WSAGetLastError on windows.
+ } while (bytes_sent < 0 && errno == EINTR);
+
+ if (bytes_sent < 0)
+ {
+ // TODO: On Windows, use WSAGEtLastError.
+ error.SetErrorToErrno();
+ num_bytes = 0;
+ }
+ else
+ num_bytes = bytes_sent;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
+ if (log)
+ {
+ log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
+ static_cast<void*>(this),
+ static_cast<uint64_t>(m_socket),
+ buf,
+ static_cast<uint64_t>(num_bytes),
+ static_cast<int64_t>(bytes_sent),
+ error.AsCString());
+ }
+
+ return error;
+}
+
+Error Socket::PreDisconnect()
+{
+ Error error;
+ return error;
+}
+
+Error Socket::Close()
+{
+ Error error;
+ if (!IsValid() || !m_should_close_fd)
+ return error;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p Socket::Close (fd = %i)", static_cast<void*>(this), m_socket);
+
+#if defined(_WIN32)
+ bool success = !!closesocket(m_socket);
+#else
+ bool success = !!::close (m_socket);
+#endif
+ // A reference to a FD was passed in, set it to an invalid value
+ m_socket = kInvalidSocketValue;
+ if (!success)
+ {
+ // TODO: On Windows, use WSAGetLastError().
+ error.SetErrorToErrno();
+ }
+
+ return error;
+}
+
+
+int Socket::GetOption(int level, int option_name, int &option_value)
+{
+ get_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
+ socklen_t option_value_size = sizeof(int);
+ return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size);
+}
+
+int Socket::SetOption(int level, int option_name, int option_value)
+{
+ set_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
+ return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value));
+}
+
+uint16_t Socket::GetPortNumber(const NativeSocket& socket)
+{
+ // We bound to port zero, so we need to figure out which port we actually bound to
+ if (socket >= 0)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getsockname (socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetPort ();
+ }
+ return 0;
+}
+
+// Return the port number that is being used by the socket.
+uint16_t Socket::GetPortNumber() const
+{
+ return GetPortNumber(m_socket);
+}
Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Wed Aug 6 13:16:26 2014
@@ -272,7 +272,8 @@ ProcessKDP::DoConnectRemote (Stream *str
if (conn_ap->IsConnected())
{
- const uint16_t reply_port = conn_ap->GetReadPort ();
+ const Socket& socket = static_cast<const Socket&>(conn_ap->GetReadObject());
+ const uint16_t reply_port = socket.GetPort();
if (reply_port != 0)
{
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Wed Aug 6 13:16:26 2014
@@ -23,6 +23,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/Socket.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Target/Process.h"
@@ -786,7 +787,7 @@ GDBRemoteCommunication::StartDebugserver
ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
// Wait for 10 seconds to resolve the bound port
- out_port = connection->GetBoundPort(10);
+ out_port = connection->GetListeningPort(10);
if (out_port > 0)
{
char port_cstr[32];
@@ -802,7 +803,6 @@ GDBRemoteCommunication::StartDebugserver
return error;
}
}
-
const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
if (env_debugserver_log_file)
Modified: lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp (original)
+++ lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp Wed Aug 6 13:16:26 2014
@@ -33,6 +33,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/OptionParser.h"
+#include "lldb/Host/Socket.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
@@ -401,9 +402,9 @@ ConnectToRemote (GDBRemoteCommunicationS
{
// FIXME use new generic named pipe support.
int fd = ::open(named_pipe_path, O_WRONLY);
- if (fd > -1)
+ const uint16_t bound_port = s_listen_connection_up->GetListeningPort(10);
+ if (fd > -1 && bound_port > 0)
{
- const uint16_t bound_port = s_listen_connection_up->GetBoundPort (10);
char port_str[64];
const ssize_t port_str_len = ::snprintf (port_str, sizeof(port_str), "%u", bound_port);
@@ -413,7 +414,10 @@ ConnectToRemote (GDBRemoteCommunicationS
}
else
{
- fprintf (stderr, "failed to open named pipe '%s' for writing\n", named_pipe_path);
+ if (fd < 0)
+ fprintf (stderr, "failed to open named pipe '%s' for writing\n", named_pipe_path);
+ else
+ fprintf(stderr, "unable to get the bound port for the listening connection\n");
}
}
Modified: lldb/trunk/tools/lldb-platform/lldb-platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-platform/lldb-platform.cpp?rev=214984&r1=214983&r2=214984&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-platform/lldb-platform.cpp (original)
+++ lldb/trunk/tools/lldb-platform/lldb-platform.cpp Wed Aug 6 13:16:26 2014
@@ -11,7 +11,9 @@
// C Includes
#include <errno.h>
-#include "lldb/Host/HostGetOpt.h"
+#if defined(__APPLE__)
+#include <netinet/in.h>
+#endif
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
@@ -27,6 +29,7 @@
#include "lldb/Core/ConnectionMachPort.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/HostGetOpt.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
More information about the lldb-commits
mailing list