diff options
| author | Chris Bieneman <beanz@apple.com> | 2017-04-26 23:17:20 +0000 |
|---|---|---|
| committer | Chris Bieneman <beanz@apple.com> | 2017-04-26 23:17:20 +0000 |
| commit | 1182779917b3c1681274e6feaa4d36e51b7e142e (patch) | |
| tree | 9c5a53efa92db6eecf0df4fd9d9e7987dcd5926e /lldb/source/Host/common/UDPSocket.cpp | |
| parent | 0fcbb2893eca48b9cf661e7ee82e8b94c89228b6 (diff) | |
| download | bcm5719-llvm-1182779917b3c1681274e6feaa4d36e51b7e142e.tar.gz bcm5719-llvm-1182779917b3c1681274e6feaa4d36e51b7e142e.zip | |
Re-landing IPv6 support for LLDB Host
This support was landed in r300579, and reverted in r300669 due to failures on the bots.
The failures were caused by sockets not being properly closed, and this updated version of the patches should resolve that.
Summary from the original change:
This patch adds IPv6 support to LLDB/Host's TCP socket implementation. Supporting IPv6 involved a few significant changes to the implementation of the socket layers, and I have performed some significant code cleanup along the way.
This patch changes the Socket constructors for all types of sockets to not create sockets until first use. This is required for IPv6 support because the socket type will vary based on the address you are connecting to. This also has the benefit of removing code that could have errors from the Socket subclass constructors (which seems like a win to me).
The patch also slightly changes the API and behaviors of the Listen/Accept pattern. Previously both Listen and Accept calls took an address specified as a string. Now only listen does. This change was made because the Listen call can result in opening more than one socket. In order to support listening for both IPv4 and IPv6 connections we need to open one AF_INET socket and one AF_INET6 socket. During the listen call we construct a map of file descriptors to addrin structures which represent the allowable incoming connection address. This map removes the need for taking an address into the Accept call.
This does have a change in functionality. Previously you could Listen for connections based on one address, and Accept connections from a different address. This is no longer supported. I could not find anywhere in LLDB where we actually used the APIs in that way. The new API does still support AnyAddr for allowing incoming connections from any address.
The Listen implementation is implemented using kqueue on FreeBSD and Darwin, WSAPoll on Windows and poll(2) everywhere else.
https://reviews.llvm.org/D31823
llvm-svn: 301492
Diffstat (limited to 'lldb/source/Host/common/UDPSocket.cpp')
| -rw-r--r-- | lldb/source/Host/common/UDPSocket.cpp | 84 |
1 files changed, 49 insertions, 35 deletions
diff --git a/lldb/source/Host/common/UDPSocket.cpp b/lldb/source/Host/common/UDPSocket.cpp index 7ca62e7496b..a32657aab0a 100644 --- a/lldb/source/Host/common/UDPSocket.cpp +++ b/lldb/source/Host/common/UDPSocket.cpp @@ -28,13 +28,16 @@ const int kDomain = AF_INET; const int kType = SOCK_DGRAM; static const char *g_not_supported_error = "Not supported"; -} +} // namespace -UDPSocket::UDPSocket(NativeSocket socket) : Socket(socket, ProtocolUdp, true) {} +UDPSocket::UDPSocket(bool should_close, bool child_processes_inherit) + : Socket(ProtocolUdp, should_close, child_processes_inherit) {} -UDPSocket::UDPSocket(bool child_processes_inherit, Error &error) - : UDPSocket( - CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {} +UDPSocket::UDPSocket(NativeSocket socket, const UDPSocket &listen_socket) + : Socket(ProtocolUdp, listen_socket.m_should_close_fd, + listen_socket.m_child_processes_inherit) { + m_socket = socket; +} size_t UDPSocket::Send(const void *buf, const size_t num_bytes) { return ::sendto(m_socket, static_cast<const char *>(buf), num_bytes, 0, @@ -42,27 +45,14 @@ size_t UDPSocket::Send(const void *buf, const size_t num_bytes) { } Error UDPSocket::Connect(llvm::StringRef name) { - return Error("%s", g_not_supported_error); -} - -Error UDPSocket::Listen(llvm::StringRef name, int backlog) { - return Error("%s", g_not_supported_error); -} - -Error UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, - Socket *&socket) { - return Error("%s", g_not_supported_error); -} - -Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, - Socket *&socket) { - std::unique_ptr<UDPSocket> final_socket; - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) log->Printf("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); Error error; + if (error.Fail()) + return error; + std::string host_str; std::string port_str; int32_t port = INT32_MIN; @@ -94,12 +84,11 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, for (struct addrinfo *service_info_ptr = service_info_list; service_info_ptr != nullptr; service_info_ptr = service_info_ptr->ai_next) { - auto send_fd = CreateSocket( + m_socket = Socket::CreateSocket( service_info_ptr->ai_family, service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol, child_processes_inherit, error); + service_info_ptr->ai_protocol, m_child_processes_inherit, error); if (error.Success()) { - final_socket.reset(new UDPSocket(send_fd)); - final_socket->m_sockaddr = service_info_ptr; + m_sockaddr = service_info_ptr; break; } else continue; @@ -107,16 +96,17 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, ::freeaddrinfo(service_info_list); - if (!final_socket) + if (IsValid()) return error; SocketAddress bind_addr; // Only bind to the loopback address if we are expecting a connection from // localhost to avoid any firewall issues. - const bool bind_addr_success = (host_str == "127.0.0.1" || host_str == "localhost") - ? bind_addr.SetToLocalhost(kDomain, port) - : bind_addr.SetToAnyAddress(kDomain, port); + const bool bind_addr_success = + (host_str == "127.0.0.1" || host_str == "localhost") + ? bind_addr.SetToLocalhost(kDomain, port) + : bind_addr.SetToAnyAddress(kDomain, port); if (!bind_addr_success) { error.SetErrorString("Failed to get hostspec to bind for"); @@ -125,13 +115,37 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, bind_addr.SetPort(0); // Let the source port # be determined dynamically - err = ::bind(final_socket->GetNativeSocket(), bind_addr, bind_addr.GetLength()); - - struct sockaddr_in source_info; - socklen_t address_len = sizeof (struct sockaddr_in); - err = ::getsockname(final_socket->GetNativeSocket(), (struct sockaddr *) &source_info, &address_len); + err = ::bind(m_socket, bind_addr, bind_addr.GetLength()); - socket = final_socket.release(); error.Clear(); return error; } + +Error UDPSocket::Listen(llvm::StringRef name, int backlog) { + return Error("%s", g_not_supported_error); +} + +Error UDPSocket::Accept(Socket *&socket) { + return Error("%s", g_not_supported_error); +} + +Error UDPSocket::CreateSocket() { + Error error; + if (IsValid()) + error = Close(); + if (error.Fail()) + return error; + m_socket = + Socket::CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error); + return error; +} + +Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, + Socket *&socket) { + std::unique_ptr<UDPSocket> final_socket( + new UDPSocket(true, child_processes_inherit)); + Error error = final_socket->Connect(name); + if (!error.Fail()) + socket = final_socket.release(); + return error; +} |

