// Copyright (c) 2016 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/header_coalescer.h"

#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "base/values.h"
#include "net/base/escape.h"
#include "net/http/http_log_util.h"
#include "net/http/http_util.h"

namespace net {
namespace {

std::unique_ptr<base::Value> ElideNetLogHeaderCallback(
    base::StringPiece header_name,
    base::StringPiece header_value,
    base::StringPiece error_message,
    NetLogCaptureMode capture_mode) {
  auto dict = std::make_unique<base::DictionaryValue>();
  dict->SetString("header_name", EscapeExternalHandlerValue(header_name));
  dict->SetString(
      "header_value",
      EscapeExternalHandlerValue(ElideHeaderValueForNetLog(
          capture_mode, header_name.as_string(), header_value.as_string())));
  dict->SetString("error", error_message);
  return std::move(dict);
}

bool ContainsUppercaseAscii(base::StringPiece str) {
  return std::any_of(str.begin(), str.end(), base::IsAsciiUpper<char>);
}

}  // namespace

HeaderCoalescer::HeaderCoalescer(uint32_t max_header_list_size,
                                 const NetLogWithSource& net_log)
    : max_header_list_size_(max_header_list_size), net_log_(net_log) {}

void HeaderCoalescer::OnHeader(base::StringPiece key, base::StringPiece value) {
  if (error_seen_)
    return;
  if (!AddHeader(key, value))
    error_seen_ = true;
}

spdy::SpdyHeaderBlock HeaderCoalescer::release_headers() {
  DCHECK(headers_valid_);
  headers_valid_ = false;
  return std::move(headers_);
}

size_t HeaderCoalescer::EstimateMemoryUsage() const {
  return base::trace_event::EstimateMemoryUsage(headers_);
}

bool HeaderCoalescer::AddHeader(base::StringPiece key,
                                base::StringPiece value) {
  if (key.empty()) {
    net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER,
                      base::Bind(&ElideNetLogHeaderCallback, key, value,
                                 "Header name must not be empty."));
    return false;
  }

  base::StringPiece key_name = key;
  if (key[0] == ':') {
    if (regular_header_seen_) {
      net_log_.AddEvent(
          NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER,
          base::Bind(&ElideNetLogHeaderCallback, key, value,
                     "Pseudo header must not follow regular headers."));
      return false;
    }
    key_name.remove_prefix(1);
  } else if (!regular_header_seen_) {
    regular_header_seen_ = true;
  }

  if (!HttpUtil::IsValidHeaderName(key_name)) {
    net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER,
                      base::Bind(&ElideNetLogHeaderCallback, key, value,
                                 "Invalid character in header name."));
    return false;
  }

  if (ContainsUppercaseAscii(key_name)) {
    net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER,
                      base::Bind(&ElideNetLogHeaderCallback, key, value,
                                 "Upper case characters in header name."));
    return false;
  }

  // 32 byte overhead according to RFC 7540 Section 6.5.2.
  header_list_size_ += key.size() + value.size() + 32;
  if (header_list_size_ > max_header_list_size_) {
    net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER,
                      base::Bind(&ElideNetLogHeaderCallback, key, value,
                                 "Header list too large."));
    return false;
  }

  // RFC 7540 Section 10.3: "Any request or response that contains a character
  // not permitted in a header field value MUST be treated as malformed (Section
  // 8.1.2.6). Valid characters are defined by the field-content ABNF rule in
  // Section 3.2 of [RFC7230]." RFC 7230 Section 3.2 says:
  // field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
  // field-vchar    = VCHAR / obs-text
  // RFC 5234 Appendix B.1 defines |VCHAR|:
  // VCHAR          =  %x21-7E
  // RFC 7230 Section 3.2.6 defines |obs-text|:
  // obs-text       = %x80-FF
  // Therefore allowed characters are '\t' (HTAB), x20 (SP), x21-7E, and x80-FF.
  for (const unsigned char c : value) {
    if (c < '\t' || ('\t' < c && c < 0x20) || c == 0x7f) {
      std::string error_line;
      base::StringAppendF(&error_line,
                          "Invalid character 0x%02X in header value.", c);
      net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER,
                        base::Bind(&ElideNetLogHeaderCallback, key, value,
                                   error_line.c_str()));
      return false;
    }
  }

  headers_.AppendValueOrAddHeader(key, value);
  return true;
}


}  // namespace net
