/*
 *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include "net/dcsctp/socket/state_cookie.h"

#include <cstdint>
#include <vector>

#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/socket/capabilities.h"
#include "rtc_base/logging.h"

namespace dcsctp {

// Magic values, which the state cookie is prefixed with.
constexpr uint32_t kMagic1 = 1684230979;
constexpr uint32_t kMagic2 = 1414541360;
constexpr size_t StateCookie::kCookieSize;

std::vector<uint8_t> StateCookie::Serialize() {
  std::vector<uint8_t> cookie;
  cookie.resize(kCookieSize);
  BoundedByteWriter<kCookieSize> buffer(cookie);
  buffer.Store32<0>(kMagic1);
  buffer.Store32<4>(kMagic2);
  buffer.Store32<8>(*initiate_tag_);
  buffer.Store32<12>(*initial_tsn_);
  buffer.Store32<16>(a_rwnd_);
  buffer.Store32<20>(static_cast<uint32_t>(*tie_tag_ >> 32));
  buffer.Store32<24>(static_cast<uint32_t>(*tie_tag_));
  buffer.Store8<28>(capabilities_.partial_reliability);
  buffer.Store8<29>(capabilities_.message_interleaving);
  buffer.Store8<30>(capabilities_.reconfig);
  buffer.Store16<32>(capabilities_.negotiated_maximum_incoming_streams);
  buffer.Store16<34>(capabilities_.negotiated_maximum_outgoing_streams);
  return cookie;
}

absl::optional<StateCookie> StateCookie::Deserialize(
    rtc::ArrayView<const uint8_t> cookie) {
  if (cookie.size() != kCookieSize) {
    RTC_DLOG(LS_WARNING) << "Invalid state cookie: " << cookie.size()
                         << " bytes";
    return absl::nullopt;
  }

  BoundedByteReader<kCookieSize> buffer(cookie);
  uint32_t magic1 = buffer.Load32<0>();
  uint32_t magic2 = buffer.Load32<4>();
  if (magic1 != kMagic1 || magic2 != kMagic2) {
    RTC_DLOG(LS_WARNING) << "Invalid state cookie; wrong magic";
    return absl::nullopt;
  }

  VerificationTag verification_tag(buffer.Load32<8>());
  TSN initial_tsn(buffer.Load32<12>());
  uint32_t a_rwnd = buffer.Load32<16>();
  uint32_t tie_tag_upper = buffer.Load32<20>();
  uint32_t tie_tag_lower = buffer.Load32<24>();
  TieTag tie_tag(static_cast<uint64_t>(tie_tag_upper) << 32 |
                 static_cast<uint64_t>(tie_tag_lower));
  Capabilities capabilities;
  capabilities.partial_reliability = buffer.Load8<28>() != 0;
  capabilities.message_interleaving = buffer.Load8<29>() != 0;
  capabilities.reconfig = buffer.Load8<30>() != 0;
  capabilities.negotiated_maximum_incoming_streams = buffer.Load16<32>();
  capabilities.negotiated_maximum_outgoing_streams = buffer.Load16<34>();

  return StateCookie(verification_tag, initial_tsn, a_rwnd, tie_tag,
                     capabilities);
}

}  // namespace dcsctp
