diff options
author | Greg Clayton <gclayton@apple.com> | 2011-07-15 16:31:38 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2011-07-15 16:31:38 +0000 |
commit | 57508026c276d9ffca1d84dfb74ea60c9b18b76a (patch) | |
tree | 1b7c2f0628ceac3e836ce9f3f0a33fc123c5d37f /lldb/source/Core/ConnectionFileDescriptor.cpp | |
parent | e9d62935d3c42cb73c39fc4d0dc46bc35dc213ec (diff) | |
download | bcm5719-llvm-57508026c276d9ffca1d84dfb74ea60c9b18b76a.tar.gz bcm5719-llvm-57508026c276d9ffca1d84dfb74ea60c9b18b76a.zip |
Added the ability to connect using "tcp://<host>:<port>" which is the
same as the old "connect://<host>:<port>". Also added the ability to
connect using "udp://<host>:<port>" which will open a connected
datagram socket. I need to find a way to specify a non connected
datagram socket as well.
We might need to start setting some settings in the URL itself,
maybe something like:
udp://<host>:<port>?connected=yes
udp://<host>:<port>?connected=no
I am open to suggestions for URL settings.
Also did more work on the KDP darwin kernel plug-in.
llvm-svn: 135277
Diffstat (limited to 'lldb/source/Core/ConnectionFileDescriptor.cpp')
-rw-r--r-- | lldb/source/Core/ConnectionFileDescriptor.cpp | 104 |
1 files changed, 101 insertions, 3 deletions
diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp index d7adc8b8bb9..f5375ca6cdf 100644 --- a/lldb/source/Core/ConnectionFileDescriptor.cpp +++ b/lldb/source/Core/ConnectionFileDescriptor.cpp @@ -97,7 +97,15 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) } else if (strstr(s, "connect://")) { - return SocketConnect (s + strlen("connect://"), error_ptr); + return ConnectTCP (s + strlen("connect://"), error_ptr); + } + else if (strstr(s, "tcp://")) + { + return ConnectTCP (s + strlen("tcp://"), error_ptr); + } + else if (strstr(s, "udp://")) + { + return ConnectUDP (s + strlen("udp://"), error_ptr); } else if (strstr(s, "fd://")) { @@ -626,10 +634,10 @@ ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_p } ConnectionStatus -ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr) +ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_ptr) { lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)", + "%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)", this, host_and_port); Close (m_fd, NULL); m_is_socket = true; @@ -715,6 +723,96 @@ ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error return eConnectionStatusSuccess; } +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_is_socket = true; + + 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) + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid host:port specification '%s'", host_and_port); + 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_DGRAM, IPPROTO_UDP); + if (m_fd == -1) + { + if (error_ptr) + error_ptr->SetErrorToErrno(); + 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) + { + 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()); + } + Close (m_fd, NULL); + return eConnectionStatusError; + } + } + + if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) + { + if (error_ptr) + error_ptr->SetErrorToErrno(); + Close (m_fd, 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(); + return eConnectionStatusSuccess; +} + #if defined(__MINGW32__) || defined(__MINGW64__) typedef const char * set_socket_option_arg_type; typedef char * get_socket_option_arg_type; |