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

namespace net {

SpdyFrameWithNameValueBlockIR::SpdyFrameWithNameValueBlockIR(
    SpdyStreamId stream_id) : SpdyFrameWithFinIR(stream_id) {}

SpdyFrameWithNameValueBlockIR::~SpdyFrameWithNameValueBlockIR() {}

SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data)
    : SpdyFrameWithFinIR(stream_id),
      pad_low_(false),
      pad_high_(false),
      padding_payload_len_(0) {
  SetDataDeep(data);
}

SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id)
    : SpdyFrameWithFinIR(stream_id),
      pad_low_(false),
      pad_high_(false),
      padding_payload_len_(0) {}

SpdyDataIR::~SpdyDataIR() {}

bool SpdyConstants::IsValidFrameType(SpdyMajorVersion version,
                                     int frame_type_field) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      // SYN_STREAM is the first valid frame.
      if (frame_type_field < SerializeFrameType(version, SYN_STREAM)) {
        return false;
      }

      // WINDOW_UPDATE is the last valid frame.
      if (frame_type_field > SerializeFrameType(version, WINDOW_UPDATE)) {
        return false;
      }

      // The valid range is non-contiguous.
      if (frame_type_field == NOOP) {
        return false;
      }

      return true;
    case SPDY4:
    case SPDY5:
      // DATA is the first valid frame.
      if (frame_type_field < SerializeFrameType(version, DATA)) {
        return false;
      }

      // BLOCKED is the last valid frame.
      if (frame_type_field > SerializeFrameType(version, BLOCKED)) {
        return false;
      }

      return true;
  }

  LOG(DFATAL) << "Unhandled SPDY version " << version;
  return false;
}

SpdyFrameType SpdyConstants::ParseFrameType(SpdyMajorVersion version,
                                            int frame_type_field) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      switch (frame_type_field) {
        case 1:
          return SYN_STREAM;
        case 2:
          return SYN_REPLY;
        case 3:
          return RST_STREAM;
        case 4:
          return SETTINGS;
        case 6:
          return PING;
        case 7:
          return GOAWAY;
        case 8:
          return HEADERS;
        case 9:
          return WINDOW_UPDATE;
      }
      break;
    case SPDY4:
    case SPDY5:
      switch (frame_type_field) {
        case 0:
          return DATA;
        case 1:
          return HEADERS;
        case 2:
          return PRIORITY;
        case 3:
          return RST_STREAM;
        case 4:
          return SETTINGS;
        case 5:
          return PUSH_PROMISE;
        case 6:
          return PING;
        case 7:
          return GOAWAY;
        case 8:
          return WINDOW_UPDATE;
        case 9:
          return CONTINUATION;
        case 10:
          return ALTSVC;
        case 11:
          return BLOCKED;
      }
      break;
  }

  LOG(DFATAL) << "Unhandled frame type " << frame_type_field;
  return DATA;
}

int SpdyConstants::SerializeFrameType(SpdyMajorVersion version,
                                      SpdyFrameType frame_type) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      switch (frame_type) {
        case SYN_STREAM:
          return 1;
        case SYN_REPLY:
          return 2;
        case RST_STREAM:
          return 3;
        case SETTINGS:
          return 4;
        case PING:
          return 6;
        case GOAWAY:
          return 7;
        case HEADERS:
          return 8;
        case WINDOW_UPDATE:
          return 9;
        default:
          LOG(DFATAL) << "Serializing unhandled frame type " << frame_type;
          return -1;
      }
    case SPDY4:
    case SPDY5:
      switch (frame_type) {
        case DATA:
          return 0;
        case HEADERS:
          return 1;
        case PRIORITY:
          return 2;
        case RST_STREAM:
          return 3;
        case SETTINGS:
          return 4;
        case PUSH_PROMISE:
          return 5;
        case PING:
          return 6;
        case GOAWAY:
          return 7;
        case WINDOW_UPDATE:
          return 8;
        case CONTINUATION:
          return 9;
        case ALTSVC:
          return 10;
        case BLOCKED:
          return 11;
        default:
          LOG(DFATAL) << "Serializing unhandled frame type " << frame_type;
          return -1;
      }
  }

  LOG(DFATAL) << "Unhandled SPDY version " << version;
  return -1;
}

bool SpdyConstants::IsValidSettingId(SpdyMajorVersion version,
                                     int setting_id_field) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      // UPLOAD_BANDWIDTH is the first valid setting id.
      if (setting_id_field <
          SerializeSettingId(version, SETTINGS_UPLOAD_BANDWIDTH)) {
        return false;
      }

      // INITIAL_WINDOW_SIZE is the last valid setting id.
      if (setting_id_field >
          SerializeSettingId(version, SETTINGS_INITIAL_WINDOW_SIZE)) {
        return false;
      }

      return true;
    case SPDY4:
    case SPDY5:
      // HEADER_TABLE_SIZE is the first valid setting id.
      if (setting_id_field <
          SerializeSettingId(version, SETTINGS_HEADER_TABLE_SIZE)) {
        return false;
      }

      // COMPRESS_DATA is the last valid setting id.
      if (setting_id_field >
          SerializeSettingId(version, SETTINGS_COMPRESS_DATA)) {
        return false;
      }

      return true;
  }

  LOG(DFATAL) << "Unhandled SPDY version " << version;
  return false;
}

SpdySettingsIds SpdyConstants::ParseSettingId(SpdyMajorVersion version,
                                              int setting_id_field) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      switch (setting_id_field) {
        case 1:
          return SETTINGS_UPLOAD_BANDWIDTH;
        case 2:
          return SETTINGS_DOWNLOAD_BANDWIDTH;
        case 3:
          return SETTINGS_ROUND_TRIP_TIME;
        case 4:
          return SETTINGS_MAX_CONCURRENT_STREAMS;
        case 5:
          return SETTINGS_CURRENT_CWND;
        case 6:
          return SETTINGS_DOWNLOAD_RETRANS_RATE;
        case 7:
          return SETTINGS_INITIAL_WINDOW_SIZE;
      }
      break;
    case SPDY4:
    case SPDY5:
      switch (setting_id_field) {
        case 1:
          return SETTINGS_HEADER_TABLE_SIZE;
        case 2:
          return SETTINGS_ENABLE_PUSH;
        case 3:
          return SETTINGS_MAX_CONCURRENT_STREAMS;
        case 4:
          return SETTINGS_INITIAL_WINDOW_SIZE;
        case 5:
          return SETTINGS_COMPRESS_DATA;
      }
      break;
  }

  LOG(DFATAL) << "Unhandled setting ID " << setting_id_field;
  return SETTINGS_UPLOAD_BANDWIDTH;
}

int SpdyConstants::SerializeSettingId(SpdyMajorVersion version,
                                       SpdySettingsIds id) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      switch (id) {
        case SETTINGS_UPLOAD_BANDWIDTH:
          return 1;
        case SETTINGS_DOWNLOAD_BANDWIDTH:
          return 2;
        case SETTINGS_ROUND_TRIP_TIME:
          return 3;
        case SETTINGS_MAX_CONCURRENT_STREAMS:
          return 4;
        case SETTINGS_CURRENT_CWND:
          return 5;
        case SETTINGS_DOWNLOAD_RETRANS_RATE:
          return 6;
        case SETTINGS_INITIAL_WINDOW_SIZE:
          return 7;
        default:
          LOG(DFATAL) << "Serializing unhandled setting id " << id;
          return -1;
      }
    case SPDY4:
    case SPDY5:
      switch (id) {
        case SETTINGS_HEADER_TABLE_SIZE:
          return 1;
        case SETTINGS_ENABLE_PUSH:
          return 2;
        case SETTINGS_MAX_CONCURRENT_STREAMS:
          return 3;
        case SETTINGS_INITIAL_WINDOW_SIZE:
          return 4;
        case SETTINGS_COMPRESS_DATA:
          return 5;
        default:
          LOG(DFATAL) << "Serializing unhandled setting id " << id;
          return -1;
      }
  }
  LOG(DFATAL) << "Unhandled SPDY version " << version;
  return -1;
}

bool SpdyConstants::IsValidRstStreamStatus(SpdyMajorVersion version,
                                           int rst_stream_status_field) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      // PROTOCOL_ERROR is the valid first status code.
      if (rst_stream_status_field <
          SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) {
        return false;
      }

      // FRAME_TOO_LARGE is the valid last status code.
      if (rst_stream_status_field >
          SerializeRstStreamStatus(version, RST_STREAM_FRAME_TOO_LARGE)) {
        return false;
      }

      return true;
    case SPDY4:
    case SPDY5:
      // NO_ERROR is the first valid status code.
      if (rst_stream_status_field <
          SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) {
        return false;
      }

      // TODO(hkhalil): Omit COMPRESSION_ERROR and SETTINGS_TIMEOUT
      /*
      // This works because GOAWAY and RST_STREAM share a namespace.
      if (rst_stream_status_field ==
          SerializeGoAwayStatus(version, GOAWAY_COMPRESSION_ERROR) ||
          rst_stream_status_field ==
          SerializeGoAwayStatus(version, GOAWAY_SETTINGS_TIMEOUT)) {
        return false;
      }
      */

      // ENHANCE_YOUR_CALM is the last valid status code.
      if (rst_stream_status_field >
          SerializeRstStreamStatus(version, RST_STREAM_ENHANCE_YOUR_CALM)) {
        return false;
      }

      return true;
  }
  LOG(DFATAL) << "Unhandled SPDY version " << version;
  return false;
}

SpdyRstStreamStatus SpdyConstants::ParseRstStreamStatus(
    SpdyMajorVersion version,
    int rst_stream_status_field) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      switch (rst_stream_status_field) {
        case 1:
          return RST_STREAM_PROTOCOL_ERROR;
        case 2:
          return RST_STREAM_INVALID_STREAM;
        case 3:
          return RST_STREAM_REFUSED_STREAM;
        case 4:
          return RST_STREAM_UNSUPPORTED_VERSION;
        case 5:
          return RST_STREAM_CANCEL;
        case 6:
          return RST_STREAM_INTERNAL_ERROR;
        case 7:
          return RST_STREAM_FLOW_CONTROL_ERROR;
        case 8:
          return RST_STREAM_STREAM_IN_USE;
        case 9:
          return RST_STREAM_STREAM_ALREADY_CLOSED;
        case 10:
          return RST_STREAM_INVALID_CREDENTIALS;
        case 11:
          return RST_STREAM_FRAME_TOO_LARGE;
      }
      break;
    case SPDY4:
    case SPDY5:
      switch (rst_stream_status_field) {
        case 1:
          return RST_STREAM_PROTOCOL_ERROR;
        case 2:
          return RST_STREAM_INTERNAL_ERROR;
        case 3:
          return RST_STREAM_FLOW_CONTROL_ERROR;
        case 5:
          return RST_STREAM_STREAM_CLOSED;
        case 6:
          return RST_STREAM_FRAME_SIZE_ERROR;
        case 7:
          return RST_STREAM_REFUSED_STREAM;
        case 8:
          return RST_STREAM_CANCEL;
        case 10:
          return RST_STREAM_CONNECT_ERROR;
        case 11:
          return RST_STREAM_ENHANCE_YOUR_CALM;
      }
      break;
  }

  LOG(DFATAL) << "Invalid RST_STREAM status " << rst_stream_status_field;
  return RST_STREAM_PROTOCOL_ERROR;
}

int SpdyConstants::SerializeRstStreamStatus(
    SpdyMajorVersion version,
    SpdyRstStreamStatus rst_stream_status) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      switch (rst_stream_status) {
        case RST_STREAM_PROTOCOL_ERROR:
          return 1;
        case RST_STREAM_INVALID_STREAM:
          return 2;
        case RST_STREAM_REFUSED_STREAM:
          return 3;
        case RST_STREAM_UNSUPPORTED_VERSION:
          return 4;
        case RST_STREAM_CANCEL:
          return 5;
        case RST_STREAM_INTERNAL_ERROR:
          return 6;
        case RST_STREAM_FLOW_CONTROL_ERROR:
          return 7;
        case RST_STREAM_STREAM_IN_USE:
          return 8;
        case RST_STREAM_STREAM_ALREADY_CLOSED:
          return 9;
        case RST_STREAM_INVALID_CREDENTIALS:
          return 10;
        case RST_STREAM_FRAME_TOO_LARGE:
          return 11;
        default:
          LOG(DFATAL) << "Unhandled RST_STREAM status "
                      << rst_stream_status;
          return -1;
      }
    case SPDY4:
    case SPDY5:
      switch (rst_stream_status) {
        case RST_STREAM_PROTOCOL_ERROR:
          return 1;
        case RST_STREAM_INTERNAL_ERROR:
          return 2;
        case RST_STREAM_FLOW_CONTROL_ERROR:
          return 3;
        case RST_STREAM_STREAM_CLOSED:
          return 5;
        case RST_STREAM_FRAME_SIZE_ERROR:
          return 6;
        case RST_STREAM_REFUSED_STREAM:
          return 7;
        case RST_STREAM_CANCEL:
          return 8;
        case RST_STREAM_CONNECT_ERROR:
          return 10;
        case RST_STREAM_ENHANCE_YOUR_CALM:
          return 11;
        default:
          LOG(DFATAL) << "Unhandled RST_STREAM status "
                      << rst_stream_status;
          return -1;
      }
  }
  LOG(DFATAL) << "Unhandled SPDY version " << version;
  return -1;
}

bool SpdyConstants::IsValidGoAwayStatus(SpdyMajorVersion version,
                                        int goaway_status_field) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      // GOAWAY_OK is the first valid status.
      if (goaway_status_field < SerializeGoAwayStatus(version, GOAWAY_OK)) {
        return false;
      }

      // GOAWAY_INTERNAL_ERROR is the last valid status.
      if (goaway_status_field > SerializeGoAwayStatus(version,
                                                      GOAWAY_INTERNAL_ERROR)) {
        return false;
      }

      return true;
    case SPDY4:
    case SPDY5:
      // GOAWAY_NO_ERROR is the first valid status.
      if (goaway_status_field < SerializeGoAwayStatus(version,
                                                      GOAWAY_NO_ERROR)) {
        return false;
      }

      // GOAWAY_INADEQUATE_SECURITY is the last valid status.
      if (goaway_status_field >
          SerializeGoAwayStatus(version, GOAWAY_INADEQUATE_SECURITY)) {
        return false;
      }

      return true;
  }
  LOG(DFATAL) << "Unknown SpdyMajorVersion " << version;
  return false;
}

SpdyGoAwayStatus SpdyConstants::ParseGoAwayStatus(SpdyMajorVersion version,
                                                  int goaway_status_field) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      switch (goaway_status_field) {
        case 0:
          return GOAWAY_OK;
        case 1:
          return GOAWAY_PROTOCOL_ERROR;
        case 2:
          return GOAWAY_INTERNAL_ERROR;
      }
      break;
    case SPDY4:
    case SPDY5:
      switch (goaway_status_field) {
        case 0:
          return GOAWAY_NO_ERROR;
        case 1:
          return GOAWAY_PROTOCOL_ERROR;
        case 2:
          return GOAWAY_INTERNAL_ERROR;
        case 3:
          return GOAWAY_FLOW_CONTROL_ERROR;
        case 4:
          return GOAWAY_SETTINGS_TIMEOUT;
        case 5:
          return GOAWAY_STREAM_CLOSED;
        case 6:
          return GOAWAY_FRAME_SIZE_ERROR;
        case 7:
          return GOAWAY_REFUSED_STREAM;
        case 8:
          return GOAWAY_CANCEL;
        case 9:
          return GOAWAY_COMPRESSION_ERROR;
        case 10:
          return GOAWAY_CONNECT_ERROR;
        case 11:
          return GOAWAY_ENHANCE_YOUR_CALM;
        case 12:
          return GOAWAY_INADEQUATE_SECURITY;
      }
      break;
  }

  LOG(DFATAL) << "Unhandled GOAWAY status " << goaway_status_field;
  return GOAWAY_PROTOCOL_ERROR;
}

SpdyMajorVersion SpdyConstants::ParseMajorVersion(int version_number) {
  switch (version_number) {
    case 2:
      return SPDY2;
    case 3:
      return SPDY3;
    case 4:
      return SPDY4;
    case 5:
      return SPDY5;
    default:
      LOG(DFATAL) << "Unsupported SPDY version number: " << version_number;
      return SPDY3;
  }
}

int SpdyConstants::SerializeMajorVersion(SpdyMajorVersion version) {
  switch (version) {
    case SPDY2:
      return 2;
    case SPDY3:
      return 3;
    case SPDY4:
      return 4;
    case SPDY5:
      return 5;
    default:
      LOG(DFATAL) << "Unsupported SPDY major version: " << version;
      return -1;
  }
}

std::string SpdyConstants::GetVersionString(SpdyMajorVersion version) {
  switch (version) {
    case SPDY2:
      return "spdy/2";
    case SPDY3:
      return "spdy/3";
    case SPDY4:
      return "spdy/4";
    case SPDY5:
      return "spdy/5";
    default:
      LOG(DFATAL) << "Unsupported SPDY major version: " << version;
      return "spdy/3";
  }
}

int SpdyConstants::SerializeGoAwayStatus(SpdyMajorVersion version,
                                         SpdyGoAwayStatus status) {
  switch (version) {
    case SPDY2:
    case SPDY3:
      // TODO(jgraettinger): Merge this back to server-side.
      switch (status) {
        case GOAWAY_NO_ERROR:
          return 0;
        case GOAWAY_PROTOCOL_ERROR:
        case GOAWAY_INTERNAL_ERROR:
        case GOAWAY_FLOW_CONTROL_ERROR:
        case GOAWAY_SETTINGS_TIMEOUT:
        case GOAWAY_STREAM_CLOSED:
        case GOAWAY_FRAME_SIZE_ERROR:
        case GOAWAY_REFUSED_STREAM:
        case GOAWAY_CANCEL:
        case GOAWAY_COMPRESSION_ERROR:
        case GOAWAY_CONNECT_ERROR:
        case GOAWAY_ENHANCE_YOUR_CALM:
        case GOAWAY_INADEQUATE_SECURITY:
          return 1;  // PROTOCOL_ERROR.
        default:
          LOG(DFATAL) << "Serializing unhandled GOAWAY status " << status;
          return -1;
      }
    case SPDY4:
    case SPDY5:
      switch (status) {
        case GOAWAY_NO_ERROR:
          return 0;
        case GOAWAY_PROTOCOL_ERROR:
          return 1;
        case GOAWAY_INTERNAL_ERROR:
          return 2;
        case GOAWAY_FLOW_CONTROL_ERROR:
          return 3;
        case GOAWAY_SETTINGS_TIMEOUT:
          return 4;
        case GOAWAY_STREAM_CLOSED:
          return 5;
        case GOAWAY_FRAME_SIZE_ERROR:
          return 6;
        case GOAWAY_REFUSED_STREAM:
          return 7;
        case GOAWAY_CANCEL:
          return 8;
        case GOAWAY_COMPRESSION_ERROR:
          return 9;
        case GOAWAY_CONNECT_ERROR:
          return 10;
        case GOAWAY_ENHANCE_YOUR_CALM:
          return 11;
        case GOAWAY_INADEQUATE_SECURITY:
          return 12;
        default:
          LOG(DFATAL) << "Serializing unhandled GOAWAY status " << status;
          return -1;
      }
  }
  LOG(DFATAL) << "Unknown SpdyMajorVersion " << version;
  return -1;
}

size_t SpdyConstants::GetDataFrameMinimumSize() {
  return 8;
}

size_t SpdyConstants::GetControlFrameHeaderSize(SpdyMajorVersion version) {
  switch (version) {
    case SPDY2:
    case SPDY3:
    case SPDY4:
    case SPDY5:
      return 8;
  }
  LOG(DFATAL) << "Unhandled SPDY version.";
  return 0;
}

size_t SpdyConstants::GetPrefixLength(SpdyFrameType type,
                                      SpdyMajorVersion version) {
  if (type != DATA) {
     return GetControlFrameHeaderSize(version);
  } else {
     return GetDataFrameMinimumSize();
  }
}

size_t SpdyConstants::GetFrameMaximumSize(SpdyMajorVersion version) {
  if (version < SPDY4) {
    // 24-bit length field plus eight-byte frame header.
    return ((1<<24) - 1) + 8;
  } else {
    // 14-bit length field.
    return (1<<14) - 1;
  }
}

size_t SpdyConstants::GetSizeOfSizeField(SpdyMajorVersion version) {
  return (version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
}

void SpdyDataIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitData(*this);
}

void SpdySynStreamIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitSynStream(*this);
}

void SpdySynReplyIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitSynReply(*this);
}

SpdyRstStreamIR::SpdyRstStreamIR(SpdyStreamId stream_id,
                                 SpdyRstStreamStatus status,
                                 base::StringPiece description)
    : SpdyFrameWithStreamIdIR(stream_id),
      description_(description) {
  set_status(status);
}

SpdyRstStreamIR::~SpdyRstStreamIR() {}

void SpdyRstStreamIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitRstStream(*this);
}

SpdySettingsIR::SpdySettingsIR()
    : clear_settings_(false),
      is_ack_(false) {}

SpdySettingsIR::~SpdySettingsIR() {}

void SpdySettingsIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitSettings(*this);
}

void SpdyPingIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitPing(*this);
}

SpdyGoAwayIR::SpdyGoAwayIR(SpdyStreamId last_good_stream_id,
                           SpdyGoAwayStatus status,
                           const base::StringPiece& description)
    : description_(description) {
      set_last_good_stream_id(last_good_stream_id);
  set_status(status);
}

SpdyGoAwayIR::~SpdyGoAwayIR() {}

const base::StringPiece& SpdyGoAwayIR::description() const {
  return description_;
}

void SpdyGoAwayIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitGoAway(*this);
}

void SpdyHeadersIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitHeaders(*this);
}

void SpdyWindowUpdateIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitWindowUpdate(*this);
}

void SpdyBlockedIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitBlocked(*this);
}

void SpdyPushPromiseIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitPushPromise(*this);
}

void SpdyContinuationIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitContinuation(*this);
}

SpdyAltSvcIR::SpdyAltSvcIR(SpdyStreamId stream_id)
    : SpdyFrameWithStreamIdIR(stream_id),
      max_age_(0),
      port_(0) {}

void SpdyAltSvcIR::Visit(SpdyFrameVisitor* visitor) const {
  return visitor->VisitAltSvc(*this);
}

}  // namespace net
