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

#include <string>

#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/net_log.h"
#include "net/base/net_util.h"
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_stream_factory_impl_job.h"
#include "net/http/http_stream_factory_impl_request.h"
#include "net/spdy/spdy_http_stream.h"
#include "url/gurl.h"

namespace net {

namespace {

GURL UpgradeUrlToHttps(const GURL& original_url, int port) {
  GURL::Replacements replacements;
  // new_sheme and new_port need to be in scope here because GURL::Replacements
  // references the memory contained by them directly.
  const std::string new_scheme = "https";
  const std::string new_port = base::IntToString(port);
  replacements.SetSchemeStr(new_scheme);
  replacements.SetPortStr(new_port);
  return original_url.ReplaceComponents(replacements);
}

}  // namespace

HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session,
                                             bool for_websockets)
    : session_(session),
      for_websockets_(for_websockets) {}

HttpStreamFactoryImpl::~HttpStreamFactoryImpl() {
  DCHECK(request_map_.empty());
  DCHECK(spdy_session_request_map_.empty());

  std::set<const Job*> tmp_job_set;
  tmp_job_set.swap(orphaned_job_set_);
  STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end());
  DCHECK(orphaned_job_set_.empty());

  tmp_job_set.clear();
  tmp_job_set.swap(preconnect_job_set_);
  STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end());
  DCHECK(preconnect_job_set_.empty());
}

HttpStreamRequest* HttpStreamFactoryImpl::RequestStream(
    const HttpRequestInfo& request_info,
    RequestPriority priority,
    const SSLConfig& server_ssl_config,
    const SSLConfig& proxy_ssl_config,
    HttpStreamRequest::Delegate* delegate,
    const BoundNetLog& net_log) {
  DCHECK(!for_websockets_);
  return RequestStreamInternal(request_info,
                               priority,
                               server_ssl_config,
                               proxy_ssl_config,
                               delegate,
                               NULL,
                               net_log);
}

HttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketHandshakeStream(
    const HttpRequestInfo& request_info,
    RequestPriority priority,
    const SSLConfig& server_ssl_config,
    const SSLConfig& proxy_ssl_config,
    HttpStreamRequest::Delegate* delegate,
    WebSocketHandshakeStreamBase::CreateHelper* create_helper,
    const BoundNetLog& net_log) {
  DCHECK(for_websockets_);
  DCHECK(create_helper);
  return RequestStreamInternal(request_info,
                               priority,
                               server_ssl_config,
                               proxy_ssl_config,
                               delegate,
                               create_helper,
                               net_log);
}

HttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal(
    const HttpRequestInfo& request_info,
    RequestPriority priority,
    const SSLConfig& server_ssl_config,
    const SSLConfig& proxy_ssl_config,
    HttpStreamRequest::Delegate* delegate,
    WebSocketHandshakeStreamBase::CreateHelper*
        websocket_handshake_stream_create_helper,
    const BoundNetLog& net_log) {
  Request* request = new Request(request_info.url,
                                 this,
                                 delegate,
                                 websocket_handshake_stream_create_helper,
                                 net_log);

  GURL alternate_url;
  AlternateProtocolInfo alternate =
      GetAlternateProtocolRequestFor(request_info.url, &alternate_url);
  Job* alternate_job = NULL;
  if (alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) {
    // Never share connection with other jobs for FTP requests.
    DCHECK(!request_info.url.SchemeIs("ftp"));

    HttpRequestInfo alternate_request_info = request_info;
    alternate_request_info.url = alternate_url;
    alternate_job =
        new Job(this, session_, alternate_request_info, priority,
                server_ssl_config, proxy_ssl_config, net_log.net_log());
    request->AttachJob(alternate_job);
    alternate_job->MarkAsAlternate(request_info.url, alternate);
  }

  Job* job = new Job(this, session_, request_info, priority,
                     server_ssl_config, proxy_ssl_config, net_log.net_log());
  request->AttachJob(job);
  if (alternate_job) {
    // Never share connection with other jobs for FTP requests.
    DCHECK(!request_info.url.SchemeIs("ftp"));

    job->WaitFor(alternate_job);
    // Make sure to wait until we call WaitFor(), before starting
    // |alternate_job|, otherwise |alternate_job| will not notify |job|
    // appropriately.
    alternate_job->Start(request);
  }
  // Even if |alternate_job| has already finished, it won't have notified the
  // request yet, since we defer that to the next iteration of the MessageLoop,
  // so starting |job| is always safe.
  job->Start(request);
  return request;
}

void HttpStreamFactoryImpl::PreconnectStreams(
    int num_streams,
    const HttpRequestInfo& request_info,
    RequestPriority priority,
    const SSLConfig& server_ssl_config,
    const SSLConfig& proxy_ssl_config) {
  DCHECK(!for_websockets_);
  GURL alternate_url;
  AlternateProtocolInfo alternate =
      GetAlternateProtocolRequestFor(request_info.url, &alternate_url);
  Job* job = NULL;
  if (alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) {
    HttpRequestInfo alternate_request_info = request_info;
    alternate_request_info.url = alternate_url;
    job = new Job(this, session_, alternate_request_info, priority,
                  server_ssl_config, proxy_ssl_config, session_->net_log());
    job->MarkAsAlternate(request_info.url, alternate);
  } else {
    job = new Job(this, session_, request_info, priority,
                  server_ssl_config, proxy_ssl_config, session_->net_log());
  }
  preconnect_job_set_.insert(job);
  job->Preconnect(num_streams);
}

const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const {
  return session_->params().host_mapping_rules;
}

AlternateProtocolInfo HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
    const GURL& original_url,
    GURL* alternate_url) {
  const AlternateProtocolInfo kNoAlternateProtocol =
      AlternateProtocolInfo(0,  UNINITIALIZED_ALTERNATE_PROTOCOL, 0);

  if (!session_->params().use_alternate_protocols)
    return kNoAlternateProtocol;

  if (original_url.SchemeIs("ftp"))
    return kNoAlternateProtocol;

  HostPortPair origin = HostPortPair(original_url.HostNoBrackets(),
                                     original_url.EffectiveIntPort());

  HttpServerProperties& http_server_properties =
      *session_->http_server_properties();
  if (!http_server_properties.HasAlternateProtocol(origin))
    return kNoAlternateProtocol;

  AlternateProtocolInfo alternate =
      http_server_properties.GetAlternateProtocol(origin);
  if (alternate.protocol == ALTERNATE_PROTOCOL_BROKEN) {
    HistogramAlternateProtocolUsage(
        ALTERNATE_PROTOCOL_USAGE_BROKEN,
        http_server_properties.GetAlternateProtocolExperiment());
    return kNoAlternateProtocol;
  }

  if (!IsAlternateProtocolValid(alternate.protocol)) {
    NOTREACHED();
    return kNoAlternateProtocol;
  }

  // Some shared unix systems may have user home directories (like
  // http://foo.com/~mike) which allow users to emit headers.  This is a bad
  // idea already, but with Alternate-Protocol, it provides the ability for a
  // single user on a multi-user system to hijack the alternate protocol.
  // These systems also enforce ports <1024 as restricted ports.  So don't
  // allow protocol upgrades to user-controllable ports.
  const int kUnrestrictedPort = 1024;
  if (!session_->params().enable_user_alternate_protocol_ports &&
      (alternate.port >= kUnrestrictedPort &&
       origin.port() < kUnrestrictedPort))
    return kNoAlternateProtocol;

  origin.set_port(alternate.port);
  if (alternate.protocol >= NPN_SPDY_MINIMUM_VERSION &&
      alternate.protocol <= NPN_SPDY_MAXIMUM_VERSION) {
    if (!HttpStreamFactory::spdy_enabled())
      return kNoAlternateProtocol;

    if (session_->HasSpdyExclusion(origin))
      return kNoAlternateProtocol;

    *alternate_url = UpgradeUrlToHttps(original_url, alternate.port);
  } else {
    DCHECK_EQ(QUIC, alternate.protocol);
    if (!session_->params().enable_quic)
        return kNoAlternateProtocol;

    // TODO(rch):  Figure out how to make QUIC iteract with PAC
    // scripts.  By not re-writing the URL, we will query the PAC script
    // for the proxy to use to reach the original URL via TCP.  But
    // the alternate request will be going via UDP to a different port.
    *alternate_url = original_url;
  }
  return alternate;
}

void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) {
  DCHECK(ContainsKey(request_map_, job));
  DCHECK_EQ(request_map_[job], request);
  DCHECK(!ContainsKey(orphaned_job_set_, job));

  request_map_.erase(job);

  orphaned_job_set_.insert(job);
  job->Orphan(request);
}

void HttpStreamFactoryImpl::OnNewSpdySessionReady(
    const base::WeakPtr<SpdySession>& spdy_session,
    bool direct,
    const SSLConfig& used_ssl_config,
    const ProxyInfo& used_proxy_info,
    bool was_npn_negotiated,
    NextProto protocol_negotiated,
    bool using_spdy,
    const BoundNetLog& net_log) {
  while (true) {
    if (!spdy_session)
      break;
    const SpdySessionKey& spdy_session_key = spdy_session->spdy_session_key();
    // Each iteration may empty out the RequestSet for |spdy_session_key| in
    // |spdy_session_request_map_|. So each time, check for RequestSet and use
    // the first one.
    //
    // TODO(willchan): If it's important, switch RequestSet out for a FIFO
    // queue (Order by priority first, then FIFO within same priority). Unclear
    // that it matters here.
    if (!ContainsKey(spdy_session_request_map_, spdy_session_key))
      break;
    Request* request = *spdy_session_request_map_[spdy_session_key].begin();
    request->Complete(was_npn_negotiated,
                      protocol_negotiated,
                      using_spdy,
                      net_log);
    if (for_websockets_) {
      // TODO(ricea): Restore this code path when WebSocket over SPDY
      // implementation is ready.
      NOTREACHED();
    } else {
      bool use_relative_url = direct || request->url().SchemeIs("https");
      request->OnStreamReady(
          NULL,
          used_ssl_config,
          used_proxy_info,
          new SpdyHttpStream(spdy_session, use_relative_url));
    }
  }
  // TODO(mbelshe): Alert other valid requests.
}

void HttpStreamFactoryImpl::OnOrphanedJobComplete(const Job* job) {
  orphaned_job_set_.erase(job);
  delete job;
}

void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) {
  preconnect_job_set_.erase(job);
  delete job;
  OnPreconnectsCompleteInternal();
}

}  // namespace net
