blob: 4a5d8f7b8833879aacd10c5f8e602403ab6809e2 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "quiche/quic/core/quic_server_id.h"
#include <optional>
#include <string>
#include <tuple>
#include <utility>
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quiche/common/platform/api/quiche_googleurl.h"
#include "quiche/common/platform/api/quiche_logging.h"
namespace quic {
// static
std::optional<QuicServerId> QuicServerId::ParseFromHostPortString(
absl::string_view host_port_string) {
url::Component username_component;
url::Component password_component;
url::Component host_component;
url::Component port_component;
url::ParseAuthority(host_port_string.data(),
url::Component(0, host_port_string.size()),
&username_component, &password_component, &host_component,
&port_component);
// Only support "host:port" and nothing more or less.
if (username_component.is_valid() || password_component.is_valid() ||
!host_component.is_nonempty() || !port_component.is_nonempty()) {
QUICHE_DVLOG(1) << "QuicServerId could not be parsed: " << host_port_string;
return std::nullopt;
}
std::string hostname(host_port_string.data() + host_component.begin,
host_component.len);
int parsed_port_number =
url::ParsePort(host_port_string.data(), port_component);
// Negative result is either invalid or unspecified, either of which is
// disallowed for this parse. Port 0 is technically valid but reserved and not
// really usable in practice, so easiest to just disallow it here.
if (parsed_port_number <= 0) {
QUICHE_DVLOG(1)
<< "Port could not be parsed while parsing QuicServerId from: "
<< host_port_string;
return std::nullopt;
}
QUICHE_DCHECK_LE(parsed_port_number, std::numeric_limits<uint16_t>::max());
return QuicServerId(std::move(hostname),
static_cast<uint16_t>(parsed_port_number));
}
QuicServerId::QuicServerId() : QuicServerId("", 0, false) {}
QuicServerId::QuicServerId(std::string host, uint16_t port)
: QuicServerId(std::move(host), port, false) {}
QuicServerId::QuicServerId(std::string host, uint16_t port,
bool privacy_mode_enabled)
: host_(std::move(host)),
port_(port),
privacy_mode_enabled_(privacy_mode_enabled) {}
QuicServerId::~QuicServerId() {}
bool QuicServerId::operator<(const QuicServerId& other) const {
return std::tie(port_, host_, privacy_mode_enabled_) <
std::tie(other.port_, other.host_, other.privacy_mode_enabled_);
}
bool QuicServerId::operator==(const QuicServerId& other) const {
return privacy_mode_enabled_ == other.privacy_mode_enabled_ &&
host_ == other.host_ && port_ == other.port_;
}
bool QuicServerId::operator!=(const QuicServerId& other) const {
return !(*this == other);
}
std::string QuicServerId::ToHostPortString() const {
return absl::StrCat(GetHostWithIpv6Brackets(), ":", port_);
}
absl::string_view QuicServerId::GetHostWithoutIpv6Brackets() const {
if (host_.length() > 2 && host_.front() == '[' && host_.back() == ']') {
return absl::string_view(host_.data() + 1, host_.length() - 2);
} else {
return host_;
}
}
std::string QuicServerId::GetHostWithIpv6Brackets() const {
if (!absl::StrContains(host_, ':') || host_.length() <= 2 ||
(host_.front() == '[' && host_.back() == ']')) {
return host_;
} else {
return absl::StrCat("[", host_, "]");
}
}
} // namespace quic