Move QuicheHostnameUtils implementation out of the platform.

Those are part of the platform API because they depend on net/base/url_util.h.  We already have half of that code copied into impl.cc file; copy the rest and move it out of platform impl directory.

(this does not actually move the file out of platform, that will be done in a follow-up CL)

PiperOrigin-RevId: 438377608
diff --git a/common/platform/api/quiche_hostname_utils.cc b/common/platform/api/quiche_hostname_utils.cc
index 57fa53c..0513cb9 100644
--- a/common/platform/api/quiche_hostname_utils.cc
+++ b/common/platform/api/quiche_hostname_utils.cc
@@ -4,18 +4,106 @@
 
 #include "common/platform/api/quiche_hostname_utils.h"
 
+#include <string>
+
 #include "absl/strings/string_view.h"
+#include "url/url_canon.h"
+#include "url/url_canon_stdstring.h"
+#include "common/platform/api/quiche_logging.h"
 
 namespace quiche {
 
+// TODO(vasilvv): the functions below are forked from Chromium's
+// net/base/url_util.h; those should be moved to googleurl.
+namespace {
+
+std::string CanonicalizeHost(absl::string_view host,
+                             url::CanonHostInfo* host_info) {
+  // Try to canonicalize the host.
+  const url::Component raw_host_component(0, static_cast<int>(host.length()));
+  std::string canon_host;
+  url::StdStringCanonOutput canon_host_output(&canon_host);
+  url::CanonicalizeHostVerbose(host.data(), raw_host_component,
+                               &canon_host_output, host_info);
+
+  if (host_info->out_host.is_nonempty() &&
+      host_info->family != url::CanonHostInfo::BROKEN) {
+    // Success!  Assert that there's no extra garbage.
+    canon_host_output.Complete();
+    QUICHE_DCHECK_EQ(host_info->out_host.len,
+                     static_cast<int>(canon_host.length()));
+  } else {
+    // Empty host, or canonicalization failed.  We'll return empty.
+    canon_host.clear();
+  }
+
+  return canon_host;
+}
+
+bool IsHostCharAlphanumeric(char c) {
+  // We can just check lowercase because uppercase characters have already been
+  // normalized.
+  return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'));
+}
+
+bool IsCanonicalizedHostCompliant(const std::string& host) {
+  if (host.empty()) {
+    return false;
+  }
+
+  bool in_component = false;
+  bool most_recent_component_started_alphanumeric = false;
+
+  for (char c : host) {
+    if (!in_component) {
+      most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c);
+      if (!most_recent_component_started_alphanumeric && (c != '-') &&
+          (c != '_')) {
+        return false;
+      }
+      in_component = true;
+    } else if (c == '.') {
+      in_component = false;
+    } else if (!IsHostCharAlphanumeric(c) && (c != '-') && (c != '_')) {
+      return false;
+    }
+  }
+
+  return most_recent_component_started_alphanumeric;
+}
+
+}  // namespace
+
 // static
 bool QuicheHostnameUtils::IsValidSNI(absl::string_view sni) {
-  return QuicheHostnameUtilsImpl::IsValidSNI(sni);
+  // TODO(rtenneti): Support RFC2396 hostname.
+  // NOTE: Microsoft does NOT enforce this spec, so if we throw away hostnames
+  // based on the above spec, we may be losing some hostnames that windows
+  // would consider valid. By far the most common hostname character NOT
+  // accepted by the above spec is '_'.
+  url::CanonHostInfo host_info;
+  std::string canonicalized_host = CanonicalizeHost(sni, &host_info);
+  return !host_info.IsIPAddress() &&
+         IsCanonicalizedHostCompliant(canonicalized_host);
 }
 
 // static
 std::string QuicheHostnameUtils::NormalizeHostname(absl::string_view hostname) {
-  return QuicheHostnameUtilsImpl::NormalizeHostname(hostname);
+  url::CanonHostInfo host_info;
+  std::string host = CanonicalizeHost(hostname, &host_info);
+
+  // Walk backwards over the string, stopping at the first trailing dot.
+  size_t host_end = host.length();
+  while (host_end != 0 && host[host_end - 1] == '.') {
+    host_end--;
+  }
+
+  // Erase the trailing dots.
+  if (host_end != host.length()) {
+    host.erase(host_end, host.length() - host_end);
+  }
+
+  return host;
 }
 
 }  // namespace quiche
diff --git a/common/platform/api/quiche_hostname_utils.h b/common/platform/api/quiche_hostname_utils.h
index a8a4acf..b9e0fb9 100644
--- a/common/platform/api/quiche_hostname_utils.h
+++ b/common/platform/api/quiche_hostname_utils.h
@@ -7,7 +7,6 @@
 
 #include <string>
 
-#include "quiche_platform_impl/quiche_hostname_utils_impl.h"
 #include "absl/strings/string_view.h"
 #include "common/platform/api/quiche_export.h"