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

#include <string>

#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/base/net_util.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"

namespace net {

namespace {

void AddSpdyHeader(const std::string& name,
                   const std::string& value,
                   SpdyHeaderBlock* headers) {
  if (headers->find(name) == headers->end()) {
    (*headers)[name] = value;
  } else {
    (*headers)[name] += '\0' + value;
  }
}

} // namespace

bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers,
                               SpdyMajorVersion protocol_version,
                               HttpResponseInfo* response) {
  std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status";
  std::string version_key =
      (protocol_version >= SPDY3) ? ":version" : "version";
  std::string version;
  std::string status;

  // The "status" header is required. "version" is required below SPDY4.
  SpdyHeaderBlock::const_iterator it;
  it = headers.find(status_key);
  if (it == headers.end())
    return false;
  status = it->second;

  if (protocol_version >= SPDY4) {
    version = "HTTP/1.1";
  } else {
    it = headers.find(version_key);
    if (it == headers.end())
      return false;
    version = it->second;
  }
  std::string raw_headers(version);
  raw_headers.push_back(' ');
  raw_headers.append(status);
  raw_headers.push_back('\0');
  for (it = headers.begin(); it != headers.end(); ++it) {
    // For each value, if the server sends a NUL-separated
    // list of values, we separate that back out into
    // individual headers for each value in the list.
    // e.g.
    //    Set-Cookie "foo\0bar"
    // becomes
    //    Set-Cookie: foo\0
    //    Set-Cookie: bar\0
    std::string value = it->second;
    size_t start = 0;
    size_t end = 0;
    do {
      end = value.find('\0', start);
      std::string tval;
      if (end != value.npos)
        tval = value.substr(start, (end - start));
      else
        tval = value.substr(start);
      if (protocol_version >= 3 && it->first[0] == ':')
        raw_headers.append(it->first.substr(1));
      else
        raw_headers.append(it->first);
      raw_headers.push_back(':');
      raw_headers.append(tval);
      raw_headers.push_back('\0');
      start = end + 1;
    } while (end != value.npos);
  }

  response->headers = new HttpResponseHeaders(raw_headers);
  response->was_fetched_via_spdy = true;
  return true;
}

void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info,
                                      const HttpRequestHeaders& request_headers,
                                      SpdyMajorVersion protocol_version,
                                      bool direct,
                                      SpdyHeaderBlock* headers) {

  HttpRequestHeaders::Iterator it(request_headers);
  while (it.GetNext()) {
    std::string name = base::StringToLowerASCII(it.name());
    if (name == "connection" || name == "proxy-connection" ||
        name == "transfer-encoding" || name == "host") {
      continue;
    }
    AddSpdyHeader(name, it.value(), headers);
  }
  static const char kHttpProtocolVersion[] = "HTTP/1.1";

  if (protocol_version < SPDY3) {
    (*headers)["version"] = kHttpProtocolVersion;
    (*headers)["method"] = info.method;
    (*headers)["host"] = GetHostAndOptionalPort(info.url);
    (*headers)["scheme"] = info.url.scheme();
    if (direct)
      (*headers)["url"] = HttpUtil::PathForRequest(info.url);
    else
      (*headers)["url"] = HttpUtil::SpecForRequest(info.url);
  } else {
    if (protocol_version < SPDY4) {
      (*headers)[":version"] = kHttpProtocolVersion;
      (*headers)[":host"] = GetHostAndOptionalPort(info.url);
    } else {
      (*headers)[":authority"] = GetHostAndOptionalPort(info.url);
    }
    (*headers)[":method"] = info.method;
    (*headers)[":scheme"] = info.url.scheme();
    (*headers)[":path"] = HttpUtil::PathForRequest(info.url);
  }
}

void CreateSpdyHeadersFromHttpResponse(
    const HttpResponseHeaders& response_headers,
    SpdyMajorVersion protocol_version,
    SpdyHeaderBlock* headers) {
  std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status";
  std::string version_key =
      (protocol_version >= SPDY3) ? ":version" : "version";

  const std::string status_line = response_headers.GetStatusLine();
  std::string::const_iterator after_version =
      std::find(status_line.begin(), status_line.end(), ' ');
  if (protocol_version < SPDY4) {
    (*headers)[version_key] = std::string(status_line.begin(), after_version);
  }
  (*headers)[status_key] = std::string(after_version + 1, status_line.end());

  void* iter = NULL;
  std::string raw_name, value;
  while (response_headers.EnumerateHeaderLines(&iter, &raw_name, &value)) {
    std::string name = base::StringToLowerASCII(raw_name);
    AddSpdyHeader(name, value, headers);
  }
}


COMPILE_ASSERT(HIGHEST - LOWEST < 4 &&
               HIGHEST - MINIMUM_PRIORITY < 5,
               request_priority_incompatible_with_spdy);

SpdyPriority ConvertRequestPriorityToSpdyPriority(
    const RequestPriority priority,
    SpdyMajorVersion protocol_version) {
  DCHECK_GE(priority, MINIMUM_PRIORITY);
  DCHECK_LE(priority, MAXIMUM_PRIORITY);
  if (protocol_version == SPDY2) {
    // SPDY 2 only has 2 bits of priority, but we have 5 RequestPriorities.
    // Map IDLE => 3, LOWEST => 2, LOW => 2, MEDIUM => 1, HIGHEST => 0.
    if (priority > LOWEST) {
      return static_cast<SpdyPriority>(HIGHEST - priority);
    } else {
      return static_cast<SpdyPriority>(HIGHEST - priority - 1);
    }
  } else {
    return static_cast<SpdyPriority>(HIGHEST - priority);
  }
}

NET_EXPORT_PRIVATE RequestPriority ConvertSpdyPriorityToRequestPriority(
    SpdyPriority priority,
    SpdyMajorVersion protocol_version) {
  // Handle invalid values gracefully, and pick LOW to map 2 back
  // to for SPDY/2.
  SpdyPriority idle_cutoff = (protocol_version == SPDY2) ? 3 : 5;
  return (priority >= idle_cutoff) ?
      IDLE : static_cast<RequestPriority>(HIGHEST - priority);
}

GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
                           SpdyMajorVersion protocol_version,
                           bool pushed) {
  // SPDY 2 server push urls are specified in a single "url" header.
  if (pushed && protocol_version == SPDY2) {
      std::string url;
      SpdyHeaderBlock::const_iterator it;
      it = headers.find("url");
      if (it != headers.end())
        url = it->second;
      return GURL(url);
  }

  const char* scheme_header = protocol_version >= SPDY3 ? ":scheme" : "scheme";
  const char* host_header = protocol_version >= SPDY4 ? ":authority" :
      (protocol_version >= SPDY3 ? ":host" : "host");
  const char* path_header = protocol_version >= SPDY3 ? ":path" : "url";

  std::string scheme;
  std::string host_port;
  std::string path;
  SpdyHeaderBlock::const_iterator it;
  it = headers.find(scheme_header);
  if (it != headers.end())
    scheme = it->second;
  it = headers.find(host_header);
  if (it != headers.end())
    host_port = it->second;
  it = headers.find(path_header);
  if (it != headers.end())
    path = it->second;

  std::string url = (scheme.empty() || host_port.empty() || path.empty())
                        ? std::string()
                        : scheme + "://" + host_port + path;
  return GURL(url);
}

}  // namespace net
