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; }
ConnectionStatus ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr) { lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)", this, host_and_port); Close (m_fd, false); 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'.\n", 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'.\n", 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'.\n", port_str.c_str()); return eConnectionStatusError; } // Create the socket m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 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; ::bzero (&sa, 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'.\n", host_str.c_str()); } Close (m_fd, false); return eConnectionStatusError; } } if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) { if (error_ptr) error_ptr->SetErrorToErrno(); Close (m_fd, false); 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; }