// Copyright (c) 2012 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 "net/http/http_server_properties.h"

#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "net/http/http_network_session.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/ssl_config.h"

namespace net {

namespace {

enum AlternativeProxyUsage {
  // Alternative Proxy was used without racing a normal connection.
  ALTERNATIVE_PROXY_USAGE_NO_RACE = 0,
  // Alternative Proxy was used by winning a race with a normal connection.
  ALTERNATIVE_PROXY_USAGE_WON_RACE = 1,
  // Alternative Proxy was not used by losing a race with a normal connection.
  ALTERNATIVE_PROXY_USAGE_LOST_RACE = 2,
  // Maximum value for the enum.
  ALTERNATIVE_PROXY_USAGE_MAX,
};

AlternativeProxyUsage ConvertProtocolUsageToProxyUsage(
    AlternateProtocolUsage usage) {
  switch (usage) {
    case ALTERNATE_PROTOCOL_USAGE_NO_RACE:
      return ALTERNATIVE_PROXY_USAGE_NO_RACE;
    case ALTERNATE_PROTOCOL_USAGE_WON_RACE:
      return ALTERNATIVE_PROXY_USAGE_WON_RACE;
    case ALTERNATE_PROTOCOL_USAGE_LOST_RACE:
      return ALTERNATIVE_PROXY_USAGE_LOST_RACE;
    default:
      NOTREACHED();
      return ALTERNATIVE_PROXY_USAGE_MAX;
  }
}

}  // anonymous namespace

const char kAlternativeServiceHeader[] = "Alt-Svc";

void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
                                     bool proxy_server_used) {
  if (proxy_server_used) {
    DCHECK_LE(usage, ALTERNATE_PROTOCOL_USAGE_LOST_RACE);
    UMA_HISTOGRAM_ENUMERATION("Net.QuicAlternativeProxy.Usage",
                              ConvertProtocolUsageToProxyUsage(usage),
                              ALTERNATIVE_PROXY_USAGE_MAX);
  } else {
    UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage", usage,
                              ALTERNATE_PROTOCOL_USAGE_MAX);
  }
}

void HistogramBrokenAlternateProtocolLocation(
    BrokenAlternateProtocolLocation location){
  UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolBrokenLocation", location,
                            BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX);
}

bool IsAlternateProtocolValid(NextProto protocol) {
  switch (protocol) {
    case kProtoUnknown:
      return false;
    case kProtoHTTP11:
      return false;
    case kProtoHTTP2:
      return true;
    case kProtoQUIC:
      return true;
  }
  NOTREACHED();
  return false;
}

// static
AlternativeServiceInfo
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
    const AlternativeService& alternative_service,
    base::Time expiration) {
  DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
  return AlternativeServiceInfo(alternative_service, expiration,
                                quic::QuicTransportVersionVector());
}

// static
AlternativeServiceInfo AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
    const AlternativeService& alternative_service,
    base::Time expiration,
    const quic::QuicTransportVersionVector& advertised_versions) {
  DCHECK_EQ(alternative_service.protocol, kProtoQUIC);
  return AlternativeServiceInfo(alternative_service, expiration,
                                advertised_versions);
}

AlternativeServiceInfo::AlternativeServiceInfo() : alternative_service_() {}

AlternativeServiceInfo::~AlternativeServiceInfo() = default;

AlternativeServiceInfo::AlternativeServiceInfo(
    const AlternativeService& alternative_service,
    base::Time expiration,
    const quic::QuicTransportVersionVector& advertised_versions)
    : alternative_service_(alternative_service), expiration_(expiration) {
  if (alternative_service_.protocol == kProtoQUIC) {
    advertised_versions_ = advertised_versions;
    std::sort(advertised_versions_.begin(), advertised_versions_.end());
  }
}

AlternativeServiceInfo::AlternativeServiceInfo(
    const AlternativeServiceInfo& alternative_service_info) = default;

AlternativeServiceInfo& AlternativeServiceInfo::operator=(
    const AlternativeServiceInfo& alternative_service_info) = default;

std::string AlternativeService::ToString() const {
  return base::StringPrintf("%s %s:%d", NextProtoToString(protocol),
                            host.c_str(), port);
}

std::string AlternativeServiceInfo::ToString() const {
  base::Time::Exploded exploded;
  expiration_.LocalExplode(&exploded);
  return base::StringPrintf(
      "%s, expires %04d-%02d-%02d %02d:%02d:%02d",
      alternative_service_.ToString().c_str(), exploded.year, exploded.month,
      exploded.day_of_month, exploded.hour, exploded.minute, exploded.second);
}

std::ostream& operator<<(std::ostream& os,
                         const AlternativeService& alternative_service) {
  os << alternative_service.ToString();
  return os;
}

// static
void HttpServerProperties::ForceHTTP11(SSLConfig* ssl_config) {
  ssl_config->alpn_protos.clear();
  ssl_config->alpn_protos.push_back(kProtoHTTP11);
}

}  // namespace net
