summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core')
-rw-r--r--lldb/source/Core/ConnectionFileDescriptor.cpp460
-rw-r--r--lldb/source/Core/DataExtractor.cpp3
2 files changed, 270 insertions, 193 deletions
diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp
index f8d44eeb2da..7d221499794 100644
--- a/lldb/source/Core/ConnectionFileDescriptor.cpp
+++ b/lldb/source/Core/ConnectionFileDescriptor.cpp
@@ -35,61 +35,88 @@
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)
+{
+ RegularExpression regex ("([^:]+):([0-9]+)");
+ if (regex.Execute (host_and_port, 2))
+ {
+ if (regex.GetMatchAtIndex (host_and_port, 1, host_str) &&
+ regex.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 (-1),
- m_fd_type (eFDTypeFile),
- m_udp_sockaddr (),
- m_udp_sockaddr_len (0),
+ m_fd_send (-1),
+ m_fd_recv (-1),
+ m_fd_send_type (eFDTypeFile),
+ m_fd_recv_type (eFDTypeFile),
m_should_close_fd (false),
m_socket_timeout_usec(0)
{
- memset (&m_udp_sockaddr, 0, sizeof(m_udp_sockaddr));
+ memset (&m_udp_send_sockaddr, 0, sizeof(m_udp_send_sockaddr));
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
- "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
- this);
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", this);
}
ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
Connection(),
- m_fd (fd),
- m_fd_type (eFDTypeFile),
- m_udp_sockaddr (),
- m_udp_sockaddr_len (0),
+ m_fd_send (fd),
+ m_fd_recv (fd),
+ m_fd_send_type (eFDTypeFile),
+ m_fd_recv_type (eFDTypeFile),
m_should_close_fd (owns_fd),
m_socket_timeout_usec(0)
{
- memset (&m_udp_sockaddr, 0, sizeof(m_udp_sockaddr));
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
- "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
- this,
- fd,
- owns_fd);
+ memset (&m_udp_send_sockaddr, 0, sizeof(m_udp_send_sockaddr));
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", this, fd, owns_fd);
}
ConnectionFileDescriptor::~ConnectionFileDescriptor ()
{
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
- "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
- this);
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", this);
Disconnect (NULL);
}
bool
ConnectionFileDescriptor::IsConnected () const
{
- return m_fd >= 0;
+ return m_fd_send >= 0 || m_fd_recv >= 0;
}
ConnectionStatus
ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
{
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
- "%p ConnectionFileDescriptor::Connect (url = '%s')",
- this,
- s);
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::Connect (url = '%s')", this, s);
if (s && s[0])
{
@@ -109,9 +136,9 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
{
return ConnectTCP (s + strlen("connect://"), error_ptr);
}
- else if (strstr(s, "tcp://"))
+ else if (strstr(s, "tcp-connect://"))
{
- return ConnectTCP (s + strlen("tcp://"), error_ptr);
+ return ConnectTCP (s + strlen("tcp-connect://"), error_ptr);
}
else if (strstr(s, "udp://"))
{
@@ -123,7 +150,8 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
// that is already opened (possibly from a service or other source).
s += strlen ("fd://");
bool success = false;
- m_fd = Args::StringToSInt32 (s, -1, 0, &success);
+ m_fd_send = m_fd_recv = Args::StringToSInt32 (s, -1, 0, &success);
+
if (success)
{
// We have what looks to be a valid file descriptor, but we
@@ -131,12 +159,12 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
// get the flags from the file descriptor and making sure it
// isn't a bad fd.
errno = 0;
- int flags = ::fcntl (m_fd, F_GETFL, 0);
+ int flags = ::fcntl (m_fd_send, F_GETFL, 0);
if (flags == -1 || errno == EBADF)
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("stale file descriptor: %s", s);
- m_fd = -1;
+ m_fd_send = m_fd_recv = -1;
return eConnectionStatusError;
}
else
@@ -144,9 +172,9 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
// 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, SOL_SOCKET, SO_REUSEADDR, resuse) == 0;
+ bool is_socket = GetSocketOption (m_fd_send, SOL_SOCKET, SO_REUSEADDR, resuse) == 0;
if (is_socket)
- m_fd_type = eFDTypeSocket;
+ m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
m_should_close_fd = true;
return eConnectionStatusSuccess;
}
@@ -154,28 +182,28 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("invalid file descriptor: \"fd://%s\"", s);
- m_fd = -1;
+ m_fd_send = m_fd_recv = -1;
return eConnectionStatusError;
}
else if (strstr(s, "file://"))
{
// file:///PATH
const char *path = s + strlen("file://");
- m_fd = ::open (path, O_RDWR);
- if (m_fd == -1)
+ m_fd_send = m_fd_recv = ::open (path, O_RDWR);
+ if (m_fd_send == -1)
{
if (error_ptr)
error_ptr->SetErrorToErrno();
return eConnectionStatusError;
}
- int flags = ::fcntl (m_fd, F_GETFL, 0);
+ int flags = ::fcntl (m_fd_send, F_GETFL, 0);
if (flags >= 0)
{
if ((flags & O_NONBLOCK) == 0)
{
flags |= O_NONBLOCK;
- ::fcntl (m_fd, F_SETFL, flags);
+ ::fcntl (m_fd_send, F_SETFL, flags);
}
}
m_should_close_fd = true;
@@ -193,15 +221,34 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
ConnectionStatus
ConnectionFileDescriptor::Disconnect (Error *error_ptr)
{
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
- "%p ConnectionFileDescriptor::Disconnect ()",
- this);
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::Disconnect ()", this);
if (m_should_close_fd == false)
{
- m_fd = -1;
+ m_fd_send = m_fd_recv = -1;
return eConnectionStatusSuccess;
}
- return Close (m_fd, error_ptr);
+ ConnectionStatus status = eConnectionStatusSuccess;
+ if (m_fd_send == m_fd_recv)
+ {
+ // Both file descriptors are the same, only close one
+ status = Close (m_fd_send, error_ptr);
+ m_fd_recv = -1;
+ }
+ else
+ {
+ // File descriptors are the different, close both if needed
+ if (m_fd_send >= 0)
+ status = Close (m_fd_send, error_ptr);
+ if (m_fd_recv >= 0)
+ {
+ ConnectionStatus recv_status = Close (m_fd_recv, error_ptr);
+ if (status == eConnectionStatusSuccess)
+ status = recv_status;
+ }
+ }
+ return status;
}
size_t
@@ -214,25 +261,23 @@ ConnectionFileDescriptor::Read (void *dst,
LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
if (log)
log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...",
- this, m_fd, dst, dst_len);
+ this, m_fd_recv, dst, dst_len);
ssize_t bytes_read = 0;
- struct sockaddr_storage from;
- socklen_t from_len = sizeof(from);
- switch (m_fd_type)
+ switch (m_fd_recv_type)
{
case eFDTypeFile: // Other FD requireing read/write
status = BytesAvailable (timeout_usec, error_ptr);
if (status == eConnectionStatusSuccess)
- bytes_read = ::read (m_fd, dst, dst_len);
+ bytes_read = ::read (m_fd_recv, dst, dst_len);
break;
case eFDTypeSocket: // Socket requiring send/recv
if (SetSocketReceiveTimeout (timeout_usec))
{
status = eConnectionStatusSuccess;
- bytes_read = ::recv (m_fd, dst, dst_len, 0);
+ bytes_read = ::recv (m_fd_recv, dst, dst_len, 0);
}
break;
@@ -240,8 +285,9 @@ ConnectionFileDescriptor::Read (void *dst,
if (SetSocketReceiveTimeout (timeout_usec))
{
status = eConnectionStatusSuccess;
- ::memset (&from, 0, sizeof(from));
- bytes_read = ::recvfrom (m_fd, dst, dst_len, 0, (struct sockaddr *)&from, &from_len);
+ sockaddr_t from = m_udp_send_sockaddr;
+ socklen_t from_len = m_udp_send_sockaddr.sa.sa_len;
+ bytes_read = ::recvfrom (m_fd_recv, dst, dst_len, 0, (struct sockaddr *)&from, &from_len);
}
break;
}
@@ -267,7 +313,7 @@ ConnectionFileDescriptor::Read (void *dst,
if (log)
log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu) => %zi, error = %s",
this,
- m_fd,
+ m_fd_recv,
dst,
dst_len,
bytes_read,
@@ -282,7 +328,10 @@ ConnectionFileDescriptor::Read (void *dst,
switch (error_value)
{
case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read.
- status = eConnectionStatusSuccess;
+ if (m_fd_recv_type == eFDTypeSocket || m_fd_recv_type == eFDTypeSocketUDP)
+ status = eConnectionStatusTimedOut;
+ else
+ status = eConnectionStatusSuccess;
return 0;
case EFAULT: // Buf points outside the allocated address space.
@@ -315,9 +364,7 @@ ConnectionFileDescriptor::Read (void *dst,
return 0;
}
-// if (log)
-// error->Log(log, "::read ( %i, %p, %zu ) => %i", m_fd, dst, dst_len, bytesread);
- Close (m_fd, NULL);
+ Disconnect (NULL);
return 0;
}
return bytes_read;
@@ -343,24 +390,24 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
ssize_t bytes_sent = 0;
- switch (m_fd_type)
+ switch (m_fd_send_type)
{
case eFDTypeFile: // Other FD requireing read/write
- bytes_sent = ::write (m_fd, src, src_len);
+ bytes_sent = ::write (m_fd_send, src, src_len);
break;
case eFDTypeSocket: // Socket requiring send/recv
- bytes_sent = ::send (m_fd, src, src_len, 0);
+ bytes_sent = ::send (m_fd_send, src, src_len, 0);
break;
case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
- assert (m_udp_sockaddr_len != 0);
- bytes_sent = ::sendto (m_fd,
+ assert (m_udp_send_sockaddr.sa_storage.ss_family != 0);
+ bytes_sent = ::sendto (m_fd_send,
src,
src_len,
0,
- (struct sockaddr *)&m_udp_sockaddr,
- m_udp_sockaddr_len);
+ &m_udp_send_sockaddr.sa,
+ m_udp_send_sockaddr.sa.sa_len);
break;
}
@@ -371,12 +418,12 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
if (log)
{
- switch (m_fd_type)
+ switch (m_fd_send_type)
{
case eFDTypeFile: // Other FD requireing read/write
log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)",
this,
- m_fd,
+ m_fd_send,
src,
src_len,
bytes_sent,
@@ -386,7 +433,7 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
case eFDTypeSocket: // Socket requiring send/recv
log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)",
this,
- m_fd,
+ m_fd_send,
src,
src_len,
bytes_sent,
@@ -396,7 +443,7 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
log->Printf ("%p ConnectionFileDescriptor::Write() ::sendto (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)",
this,
- m_fd,
+ m_fd_send,
src,
src_len,
bytes_sent,
@@ -427,7 +474,7 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
break; // Break to close....
}
- Close (m_fd, NULL);
+ Disconnect (NULL);
return 0;
}
@@ -460,16 +507,15 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
{
fd_set read_fds;
FD_ZERO (&read_fds);
- FD_SET (m_fd, &read_fds);
- int nfds = m_fd + 1;
+ FD_SET (m_fd_recv, &read_fds);
+ int nfds = m_fd_recv + 1;
Error error;
- log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
if (log)
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p)...",
- this, nfds, m_fd, tv_ptr);
+ this, nfds, m_fd_recv, tv_ptr);
const int num_set_fds = ::select (nfds, &read_fds, NULL, NULL, tv_ptr);
if (num_set_fds < 0)
@@ -477,10 +523,9 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
else
error.Clear();
- log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
if (log)
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p) => %d, error = %s",
- this, nfds, m_fd, tv_ptr, num_set_fds, error.AsCString());
+ this, nfds, m_fd_recv, tv_ptr, num_set_fds, error.AsCString());
if (error_ptr)
*error_ptr = error;
@@ -528,10 +573,9 @@ ConnectionFileDescriptor::Close (int& fd, Error *error_ptr)
bool success = true;
if (fd >= 0)
{
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
- "%p ConnectionFileDescriptor::Close (fd = %i)",
- this,
- fd);
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::Close (fd = %i)", this,fd);
success = ::close (fd) == 0;
if (!success && error_ptr)
@@ -543,7 +587,7 @@ ConnectionFileDescriptor::Close (int& fd, Error *error_ptr)
}
fd = -1;
}
- m_fd_type = eFDTypeFile;
+ m_fd_send_type = m_fd_recv_type = eFDTypeFile;
if (success)
return eConnectionStatusSuccess;
else
@@ -556,7 +600,7 @@ ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *err
ConnectionStatus result = eConnectionStatusError;
struct sockaddr_un saddr_un;
- m_fd_type = eFDTypeSocket;
+ m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0);
if (listen_socket == -1)
@@ -577,8 +621,8 @@ ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *err
{
if (::listen (listen_socket, 5) == 0)
{
- m_fd = ::accept (listen_socket, NULL, 0);
- if (m_fd > 0)
+ m_fd_send = m_fd_recv = ::accept (listen_socket, NULL, 0);
+ if (m_fd_send > 0)
{
m_should_close_fd = true;
@@ -602,13 +646,13 @@ ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *err
ConnectionStatus
ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *error_ptr)
{
- Close (m_fd, NULL);
- m_fd_type = eFDTypeSocket;
+ Disconnect (NULL);
+ m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
// Open the socket that was passed in as an option
struct sockaddr_un saddr_un;
- m_fd = ::socket (AF_UNIX, SOCK_STREAM, 0);
- if (m_fd == -1)
+ m_fd_send = m_fd_recv = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (m_fd_send == -1)
{
if (error_ptr)
error_ptr->SetErrorToErrno();
@@ -622,11 +666,11 @@ ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *er
saddr_un.sun_len = SUN_LEN (&saddr_un);
#endif
- if (::connect (m_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
+ if (::connect (m_fd_send, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
{
if (error_ptr)
error_ptr->SetErrorToErrno();
- Close (m_fd, NULL);
+ Disconnect (NULL);
return eConnectionStatusError;
}
if (error_ptr)
@@ -637,12 +681,12 @@ ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *er
ConnectionStatus
ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_ptr)
{
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
- "%p ConnectionFileDescriptor::SocketListen (port = %i)",
- this, listen_port_num);
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::SocketListen (port = %i)", this, listen_port_num);
- Close (m_fd, NULL);
- m_fd_type = eFDTypeSocket;
+ Disconnect (NULL);
+ m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_port == -1)
{
@@ -678,8 +722,8 @@ ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_p
return eConnectionStatusError;
}
- m_fd = ::accept (listen_port, NULL, 0);
- if (m_fd == -1)
+ m_fd_send = m_fd_recv = ::accept (listen_port, NULL, 0);
+ if (m_fd_send == -1)
{
if (error_ptr)
error_ptr->SetErrorToErrno();
@@ -693,7 +737,7 @@ ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_p
m_should_close_fd = true;
// Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
+ SetSocketOption (m_fd_send, IPPROTO_TCP, TCP_NODELAY, 1);
if (error_ptr)
error_ptr->Clear();
return eConnectionStatusSuccess;
@@ -702,39 +746,21 @@ ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_p
ConnectionStatus
ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_ptr)
{
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
- "%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)",
- this, host_and_port);
- Close (m_fd, NULL);
- m_fd_type = eFDTypeSocket;
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)", this, host_and_port);
+ Disconnect (NULL);
- RegularExpression regex ("([^:]+):([0-9]+)");
- if (regex.Execute (host_and_port, 2) == false)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port);
- return eConnectionStatusError;
- }
+ m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
std::string host_str;
std::string port_str;
- if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false ||
- regex.GetMatchAtIndex (host_and_port, 2, port_str) == false)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid host:port specification '%s'", host_and_port);
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr))
return eConnectionStatusError;
- }
- int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
- if (port == INT32_MIN)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid port '%s'", port_str.c_str());
- return eConnectionStatusError;
- }
// Create the socket
- m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (m_fd == -1)
+ m_fd_send = m_fd_recv = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (m_fd_send == -1)
{
if (error_ptr)
error_ptr->SetErrorToErrno();
@@ -744,7 +770,7 @@ ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_pt
m_should_close_fd = true;
// Enable local address reuse
- SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
+ SetSocketOption (m_fd_send, SOL_SOCKET, SO_REUSEADDR, 1);
struct sockaddr_in sa;
::memset (&sa, 0, sizeof (sa));
@@ -769,21 +795,23 @@ ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_pt
else
error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
}
- Close (m_fd, NULL);
+ Disconnect (NULL);
+
return eConnectionStatusError;
}
}
- if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa)))
+ if (-1 == ::connect (m_fd_send, (const struct sockaddr *)&sa, sizeof(sa)))
{
if (error_ptr)
error_ptr->SetErrorToErrno();
- Close (m_fd, NULL);
+ Disconnect (NULL);
+
return eConnectionStatusError;
}
// Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
+ SetSocketOption (m_fd_send, IPPROTO_TCP, TCP_NODELAY, 1);
if (error_ptr)
error_ptr->Clear();
return eConnectionStatusSuccess;
@@ -792,90 +820,104 @@ ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_pt
ConnectionStatus
ConnectionFileDescriptor::ConnectUDP (const char *host_and_port, Error *error_ptr)
{
- lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
- "%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)",
- this, host_and_port);
- Close (m_fd, NULL);
- m_fd_type = eFDTypeSocketUDP;
+ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)", this, host_and_port);
+ Disconnect (NULL);
+
+ m_fd_send_type = m_fd_recv_type = eFDTypeSocketUDP;
- RegularExpression regex ("([^:]+):([0-9]+)");
- if (regex.Execute (host_and_port, 2) == false)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port);
- return eConnectionStatusError;
- }
std::string host_str;
std::string port_str;
- if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false ||
- regex.GetMatchAtIndex (host_and_port, 2, port_str) == false)
+ 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->SetErrorStringWithFormat("invalid host:port specification '%s'", host_and_port);
- return eConnectionStatusError;
+ error_ptr->SetErrorToErrno();
}
-
- int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
- if (port == INT32_MIN)
+ else
{
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid port '%s'", port_str.c_str());
- return eConnectionStatusError;
+ // Socket was created, now lets bind to the requested port
+ struct sockaddr_in sin;
+ ::memset (&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = 0;
+ sin.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ if (::bind (m_fd_recv, (struct sockaddr *)&sin, sizeof(sin)) == -1)
+ {
+ // Bind failed...
+ if (error_ptr)
+ error_ptr->SetErrorToErrno();
+ Disconnect (NULL);
+ }
}
- // Create the socket
- m_fd = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (m_fd == -1)
+
+ if (m_fd_recv == -1)
+ return eConnectionStatusError;
+
+ // At this point we have setup the recieve 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->SetErrorToErrno();
- return eConnectionStatusError;
+ 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;
}
- m_should_close_fd = true;
-
- // Enable local address reuse
- SetSocketOption (m_fd, 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)
+ for (struct addrinfo *service_info_ptr = service_info_list;
+ service_info_ptr != NULL;
+ service_info_ptr = service_info_ptr->ai_next)
{
- 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)
+ m_fd_send = ::socket (service_info_ptr->ai_family,
+ service_info_ptr->ai_socktype,
+ service_info_ptr->ai_protocol);
+
+ if (m_fd_send != -1)
{
-
- if (error_ptr)
- {
- if (inet_pton_result == -1)
- error_ptr->SetErrorToErrno();
- else
- error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
- }
- Close (m_fd, NULL);
- return eConnectionStatusError;
+ ::memset (&m_udp_send_sockaddr, 0, sizeof(m_udp_send_sockaddr));
+ ::memcpy (&m_udp_send_sockaddr,
+ service_info_ptr->ai_addr,
+ service_info_ptr->ai_addrlen);
+ break;
}
+ else
+ continue;
}
- if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa)))
+ :: freeaddrinfo (service_info_list);
+
+ if (m_fd_send == -1)
{
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Close (m_fd, NULL);
+ Disconnect (NULL);
return eConnectionStatusError;
}
-
- // Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
+
if (error_ptr)
error_ptr->Clear();
+
+ m_should_close_fd = true;
return eConnectionStatusSuccess;
}
@@ -905,7 +947,7 @@ ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, in
bool
ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec)
{
- switch (m_fd_type)
+ switch (m_fd_recv_type)
{
case eFDTypeFile: // Other FD requireing read/write
break;
@@ -921,7 +963,7 @@ ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec)
struct timeval timeout;
timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec;
timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec;
- if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0)
+ if (::setsockopt (m_fd_recv, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0)
{
m_socket_timeout_usec = timeout_usec;
return true;
@@ -931,4 +973,38 @@ ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec)
return false;
}
+in_port_t
+ConnectionFileDescriptor::GetSocketPort (int fd)
+{
+ // We bound to port zero, so we need to figure out which port we actually bound to
+ sockaddr_t sock_addr;
+ socklen_t sock_addr_len = sizeof (sock_addr);
+ if (::getsockname (fd, &sock_addr.sa, &sock_addr_len) == 0)
+ {
+ switch (sock_addr.sa.sa_family)
+ {
+ case AF_INET: return sock_addr.sa_ipv4.sin_port;
+ case AF_INET6: return sock_addr.sa_ipv6.sin6_port;
+ }
+ }
+ return 0;
+
+}
+
+// If the read file descriptor is a socket, then return
+// the port number that is being used by the socket.
+in_port_t
+ConnectionFileDescriptor::GetReadPort () const
+{
+ return ConnectionFileDescriptor::GetSocketPort (m_fd_recv);
+}
+
+// If the write file descriptor is a socket, then return
+// the port number that is being used by the socket.
+in_port_t
+ConnectionFileDescriptor::GetWritePort () const
+{
+ return ConnectionFileDescriptor::GetSocketPort (m_fd_send);
+}
+
diff --git a/lldb/source/Core/DataExtractor.cpp b/lldb/source/Core/DataExtractor.cpp
index 9518b44cffb..e364dfd6097 100644
--- a/lldb/source/Core/DataExtractor.cpp
+++ b/lldb/source/Core/DataExtractor.cpp
@@ -1793,6 +1793,7 @@ void
DataExtractor::DumpHexBytes (Stream *s,
const void *src,
size_t src_len,
+ uint32_t bytes_per_line,
addr_t base_addr)
{
DataExtractor data (src, src_len, eByteOrderLittle, 4);
@@ -1801,7 +1802,7 @@ DataExtractor::DumpHexBytes (Stream *s,
eFormatBytes, // Dump as hex bytes
1, // Size of each item is 1 for single bytes
src_len, // Number of bytes
- 32, // Num bytes per line
+ bytes_per_line, // Num bytes per line
base_addr, // Base address
0, 0); // Bitfield info
}
OpenPOWER on IntegriCloud