// Copyright 2017 The Fuchsia 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 "src/connectivity/network/mdns/service/dns_writing.h"

#include <lib/syslog/cpp/macros.h>

#include <limits>

namespace mdns {

PacketWriter& operator<<(PacketWriter& writer, const DnsName& value) {
  std::string s = value.dotted_string_;

  while (!s.empty()) {
    size_t position = writer.GetBookmarkPosition(s);
    if (position != PacketWriter::npos) {
      // Write a name offset.
      uint16_t offset = static_cast<uint16_t>(position) | 0xc000;
      writer << offset;
      return writer;
    }

    writer.CreateBookmark(s);

    size_t dot_pos = s.find('.');

    if (dot_pos == std::string::npos) {
      // There really should be a dot at the end, but there is not.
      writer << static_cast<uint8_t>(s.size());
      writer.PutBytes(s.size(), s.data());
      break;
    }

    writer << static_cast<uint8_t>(dot_pos);
    writer.PutBytes(dot_pos, s.data());
    s = s.substr(dot_pos + 1);
  }

  return writer << static_cast<uint8_t>(0);
}

PacketWriter& operator<<(PacketWriter& writer, const DnsV4Address& value) {
  FX_DCHECK(value.address_.is_v4());
  writer.PutBytes(value.address_.byte_count(), value.address_.as_bytes());
  return writer;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsV6Address& value) {
  FX_DCHECK(value.address_.is_v6());
  writer.PutBytes(value.address_.byte_count(), value.address_.as_bytes());
  return writer;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsType& value) {
  uint16_t as_uint16 = static_cast<uint16_t>(value);
  return writer << as_uint16;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsClass& value) {
  uint16_t as_uint16 = static_cast<uint16_t>(value);
  return writer << as_uint16;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsClassAndFlag& value) {
  uint16_t as_uint16 = static_cast<uint16_t>(value.class_);
  if (value.flag_) {
    as_uint16 |= 0x8000;
  }
  return writer << as_uint16;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsHeader& value) {
  return writer << value.id_ << value.flags_ << value.question_count_ << value.answer_count_
                << value.authority_count_ << value.additional_count_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsQuestion& value) {
  DnsClassAndFlag class_and_flag;
  class_and_flag.class_ = value.class_;
  class_and_flag.flag_ = value.unicast_response_;
  return writer << value.name_ << value.type_ << class_and_flag;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataA& value) {
  return writer << value.address_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataNs& value) {
  return writer << value.name_server_domain_name_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataCName& value) {
  return writer << value.canonical_name_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataPtr& value) {
  return writer << value.pointer_domain_name_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataTxt& value) {
  for (auto& string : value.strings_) {
    if (string.size() > std::numeric_limits<uint8_t>::max()) {
      continue;
    }

    writer << static_cast<uint8_t>(string.size());
    writer.PutBytes(string.size(), string.data());
  }

  return writer << static_cast<uint8_t>(0);
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataAaaa& value) {
  return writer << value.address_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataSrv& value) {
  return writer << value.priority_ << value.weight_ << value.port_.as_uint16_t() << value.target_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataOpt& value) {
  uint16_t length = value.options_.size();
  return writer << length << value.options_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResourceDataNSec& value) {
  return writer << value.next_domain_ << value.bits_;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsResource& value) {
  DnsClassAndFlag class_and_flag;
  class_and_flag.class_ = value.class_;
  class_and_flag.flag_ = value.cache_flush_;

  writer << value.name_ << value.type_ << class_and_flag << value.time_to_live_;

  // Note where the data size goes and write a placeholder.
  size_t data_size_position = writer.position();
  uint16_t data_size = 0;

  writer << data_size;

  switch (value.type_) {
    case DnsType::kA:
      writer << value.a_;
      break;
    case DnsType::kNs:
      writer << value.ns_;
      break;
    case DnsType::kCName:
      writer << value.cname_;
      break;
    case DnsType::kPtr:
      writer << value.ptr_;
      break;
    case DnsType::kTxt:
      writer << value.txt_;
      break;
    case DnsType::kAaaa:
      writer << value.aaaa_;
      break;
    case DnsType::kSrv:
      writer << value.srv_;
      break;
    case DnsType::kOpt:
      writer << value.opt_;
      break;
    case DnsType::kNSec:
      writer << value.nsec_;
      break;
    default:
      FX_DCHECK(false) << "Unsupported resource type " << static_cast<uint16_t>(value.type_);
      break;
  }

  // Determine the size of the data and prefix the data with it.
  size_t end_position = writer.position();
  data_size = end_position - data_size_position - sizeof(data_size);
  writer.SetPosition(data_size_position);
  writer << data_size;
  writer.SetPosition(end_position);

  return writer;
}

PacketWriter& operator<<(PacketWriter& writer, const DnsMessage& value) {
  FX_DCHECK(value.header_.question_count_ == value.questions_.size());
  FX_DCHECK(value.header_.answer_count_ == value.answers_.size());
  FX_DCHECK(value.header_.authority_count_ == value.authorities_.size());
  FX_DCHECK(value.header_.additional_count_ == value.additionals_.size());

  writer << value.header_;

  for (uint16_t i = 0; i < value.questions_.size(); ++i) {
    writer << value.questions_[i];
  }

  for (uint16_t i = 0; i < value.answers_.size(); ++i) {
    writer << value.answers_[i];
  }

  for (uint16_t i = 0; i < value.authorities_.size(); ++i) {
    writer << value.authorities_[i];
  }

  for (uint16_t i = 0; i < value.additionals_.size(); ++i) {
    writer << value.additionals_[i];
  }

  return writer;
}

}  // namespace mdns
