// 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_stream_factory.h"

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "net/base/host_mapping_rules.h"
#include "net/base/host_port_pair.h"
#include "net/http/http_network_session.h"
#include "url/gurl.h"

namespace net {

// WARNING: If you modify or add any static flags, you must keep them in sync
// with |ResetStaticSettingsToInit|. This is critical for unit test isolation.

// static
bool HttpStreamFactory::spdy_enabled_ = true;

HttpStreamFactory::~HttpStreamFactory() {}

// static
void HttpStreamFactory::ResetStaticSettingsToInit() {
  spdy_enabled_ = true;
}

void HttpStreamFactory::ProcessAlternateProtocol(
    const base::WeakPtr<HttpServerProperties>& http_server_properties,
    const std::vector<std::string>& alternate_protocol_values,
    const HostPortPair& http_host_port_pair,
    const HttpNetworkSession& session) {
  AlternateProtocol protocol = UNINITIALIZED_ALTERNATE_PROTOCOL;
  int port = 0;
  double probability = 1;
  for (size_t i = 0; i < alternate_protocol_values.size(); ++i) {
    const std::string& alternate_protocol_str = alternate_protocol_values[i];
    if (StartsWithASCII(alternate_protocol_str, "p=", true)) {
      if (!base::StringToDouble(alternate_protocol_str.substr(2),
                                &probability) ||
          probability < 0 || probability > 1) {
        DVLOG(1) << kAlternateProtocolHeader
                 << " header has unrecognizable probability: "
                 << alternate_protocol_values[i];
        return;
      }
      continue;
    }

    std::vector<std::string> port_protocol_vector;
    base::SplitString(alternate_protocol_str, ':', &port_protocol_vector);
    if (port_protocol_vector.size() != 2) {
      DVLOG(1) << kAlternateProtocolHeader
               << " header has too many tokens: "
               << alternate_protocol_str;
      return;
    }

    if (!base::StringToInt(port_protocol_vector[0], &port) ||
        port == 0 || !IsPortValid(port)) {
      DVLOG(1) << kAlternateProtocolHeader
               << " header has unrecognizable port: "
               << port_protocol_vector[0];
      return;
    }

    protocol = AlternateProtocolFromString(port_protocol_vector[1]);

    if (IsAlternateProtocolValid(protocol) &&
        !session.IsProtocolEnabled(protocol)) {
      DVLOG(1) << kAlternateProtocolHeader
               << " header has unrecognized protocol: "
               << port_protocol_vector[1];
      return;
    }
  }

  if (protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
    return;

  HostPortPair host_port(http_host_port_pair);
  const HostMappingRules* mapping_rules = GetHostMappingRules();
  if (mapping_rules)
    mapping_rules->RewriteHost(&host_port);

  if (http_server_properties->HasAlternateProtocol(host_port)) {
    const AlternateProtocolInfo existing_alternate =
        http_server_properties->GetAlternateProtocol(host_port);
    // If we think the alternate protocol is broken, don't change it.
    if (existing_alternate.is_broken)
      return;
  }

  http_server_properties->SetAlternateProtocol(
      host_port, static_cast<uint16>(port), protocol, probability);
}

GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
                                              HostPortPair* endpoint) {
  const HostMappingRules* mapping_rules = GetHostMappingRules();
  if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
    url::Replacements<char> replacements;
    const std::string port_str = base::IntToString(endpoint->port());
    replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
    replacements.SetHost(endpoint->host().c_str(),
                         url::Component(0, endpoint->host().size()));
    return url.ReplaceComponents(replacements);
  }
  return url;
}

HttpStreamFactory::HttpStreamFactory() {}

}  // namespace net
