// Copyright 2015 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/websockets/websocket_deflate_parameters.h"

#include "base/strings/string_number_conversions.h"

namespace net {

namespace {

const WebSocketDeflater::ContextTakeOverMode kTakeOverContext =
    WebSocketDeflater::TAKE_OVER_CONTEXT;
const WebSocketDeflater::ContextTakeOverMode kDoNotTakeOverContext =
    WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT;

const char kServerNoContextTakeOver[] = "server_no_context_takeover";
const char kClientNoContextTakeOver[] = "client_no_context_takeover";
const char kServerMaxWindowBits[] = "server_max_window_bits";
const char kClientMaxWindowBits[] = "client_max_window_bits";
const char kExtensionName[] = "permessage-deflate";

bool GetWindowBits(const std::string& value, int* window_bits) {
  return !value.empty() && value[0] != '0' &&
         value.find_first_not_of("0123456789") == std::string::npos &&
         base::StringToInt(value, window_bits);
}

bool DuplicateError(const std::string& name, std::string* failure_message) {
  *failure_message =
      "Received duplicate permessage-deflate extension parameter " + name;
  return false;
}

bool InvalidError(const std::string& name, std::string* failure_message) {
  *failure_message = "Received invalid " + name + " parameter";
  return false;
}

}  // namespace

WebSocketExtension WebSocketDeflateParameters::AsExtension() const {
  WebSocketExtension e(kExtensionName);

  if (server_context_take_over_mode_ == kDoNotTakeOverContext)
    e.Add(WebSocketExtension::Parameter(kServerNoContextTakeOver));
  if (client_context_take_over_mode_ == kDoNotTakeOverContext)
    e.Add(WebSocketExtension::Parameter(kClientNoContextTakeOver));
  if (is_server_max_window_bits_specified()) {
    DCHECK(server_max_window_bits_.has_value);
    e.Add(WebSocketExtension::Parameter(
        kServerMaxWindowBits, base::NumberToString(server_max_window_bits())));
  }
  if (is_client_max_window_bits_specified()) {
    if (has_client_max_window_bits_value()) {
      e.Add(WebSocketExtension::Parameter(
          kClientMaxWindowBits,
          base::NumberToString(client_max_window_bits())));
    } else {
      e.Add(WebSocketExtension::Parameter(kClientMaxWindowBits));
    }
  }

  return e;
}

bool WebSocketDeflateParameters::IsValidAsRequest(std::string*) const {
  if (server_max_window_bits_.is_specified) {
    DCHECK(server_max_window_bits_.has_value);
    DCHECK(IsValidWindowBits(server_max_window_bits_.bits));
  }
  if (client_max_window_bits_.is_specified &&
      client_max_window_bits_.has_value) {
    DCHECK(IsValidWindowBits(client_max_window_bits_.bits));
  }
  return true;
}

bool WebSocketDeflateParameters::IsValidAsResponse(
    std::string* failure_message) const {
  if (server_max_window_bits_.is_specified) {
    DCHECK(server_max_window_bits_.has_value);
    DCHECK(IsValidWindowBits(server_max_window_bits_.bits));
  }
  if (client_max_window_bits_.is_specified) {
    if (!client_max_window_bits_.has_value) {
      *failure_message = "client_max_window_bits must have value";
      return false;
    }
    DCHECK(IsValidWindowBits(client_max_window_bits_.bits));
  }

  return true;
}

bool WebSocketDeflateParameters::Initialize(const WebSocketExtension& extension,
                                            std::string* failure_message) {
  *this = WebSocketDeflateParameters();

  if (extension.name() != kExtensionName) {
    *failure_message = "extension name doesn't match";
    return false;
  }
  for (const auto& p : extension.parameters()) {
    if (p.name() == kServerNoContextTakeOver) {
      if (server_context_take_over_mode() == kDoNotTakeOverContext)
        return DuplicateError(p.name(), failure_message);
      if (p.HasValue())
        return InvalidError(p.name(), failure_message);
      SetServerNoContextTakeOver();
    } else if (p.name() == kClientNoContextTakeOver) {
      if (client_context_take_over_mode() == kDoNotTakeOverContext)
        return DuplicateError(p.name(), failure_message);
      if (p.HasValue())
        return InvalidError(p.name(), failure_message);
      SetClientNoContextTakeOver();
    } else if (p.name() == kServerMaxWindowBits) {
      if (server_max_window_bits_.is_specified)
        return DuplicateError(p.name(), failure_message);
      int bits;
      if (!GetWindowBits(p.value(), &bits) || !IsValidWindowBits(bits))
        return InvalidError(p.name(), failure_message);
      SetServerMaxWindowBits(bits);
    } else if (p.name() == kClientMaxWindowBits) {
      if (client_max_window_bits_.is_specified)
        return DuplicateError(p.name(), failure_message);
      if (p.value().empty()) {
        SetClientMaxWindowBits();
      } else {
        int bits;
        if (!GetWindowBits(p.value(), &bits) || !IsValidWindowBits(bits))
          return InvalidError(p.name(), failure_message);
        SetClientMaxWindowBits(bits);
      }
    } else {
      *failure_message =
          "Received an unexpected permessage-deflate extension parameter";
      return false;
    }
  }
  return true;
}

bool WebSocketDeflateParameters::IsCompatibleWith(
    const WebSocketDeflateParameters& response) const {
  const auto& request = *this;
  DCHECK(request.IsValidAsRequest());
  DCHECK(response.IsValidAsResponse());

  // server_no_context_take_over
  if (request.server_context_take_over_mode() == kDoNotTakeOverContext &&
      response.server_context_take_over_mode() == kTakeOverContext) {
    return false;
  }

  // No compatibility check is needed for client_no_context_take_over

  // server_max_window_bits
  if (request.server_max_window_bits_.is_specified) {
    DCHECK(request.server_max_window_bits_.has_value);
    if (!response.server_max_window_bits_.is_specified)
      return false;
    DCHECK(response.server_max_window_bits_.has_value);
    if (request.server_max_window_bits_.bits <
        response.server_max_window_bits_.bits) {
      return false;
    }
  }

  // client_max_window_bits
  if (!request.client_max_window_bits_.is_specified &&
      response.client_max_window_bits_.is_specified) {
    return false;
  }

  return true;
}

}  // namespace net
