// Copyright (c) 2013 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/dns/mdns_cache.h"

#include <algorithm>
#include <utility>

#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/record_parsed.h"
#include "net/dns/record_rdata.h"

// TODO(noamsml): Recursive CNAME closure (backwards and forwards).

namespace net {

// The effective TTL given to records with a nominal zero TTL.
// Allows time for hosts to send updated records, as detailed in RFC 6762
// Section 10.1.
static const unsigned kZeroTTLSeconds = 1;

MDnsCache::Key::Key(unsigned type, const std::string& name,
                    const std::string& optional)
    : type_(type), name_(name), optional_(optional) {
}

MDnsCache::Key::Key(
    const MDnsCache::Key& other)
    : type_(other.type_), name_(other.name_), optional_(other.optional_) {
}


MDnsCache::Key& MDnsCache::Key::operator=(
    const MDnsCache::Key& other) {
  type_ = other.type_;
  name_ = other.name_;
  optional_ = other.optional_;
  return *this;
}

MDnsCache::Key::~Key() {
}

bool MDnsCache::Key::operator<(const MDnsCache::Key& key) const {
  if (name_ != key.name_)
    return name_ < key.name_;

  if (type_ != key.type_)
    return type_ < key.type_;

  if (optional_ != key.optional_)
    return optional_ < key.optional_;
  return false;  // keys are equal
}

bool MDnsCache::Key::operator==(const MDnsCache::Key& key) const {
  return type_ == key.type_ && name_ == key.name_ && optional_ == key.optional_;
}

// static
MDnsCache::Key MDnsCache::Key::CreateFor(const RecordParsed* record) {
  return Key(record->type(),
             record->name(),
             GetOptionalFieldForRecord(record));
}


MDnsCache::MDnsCache() {
}

MDnsCache::~MDnsCache() {
  Clear();
}

void MDnsCache::Clear() {
  next_expiration_ = base::Time();
  STLDeleteValues(&mdns_cache_);
}

const RecordParsed* MDnsCache::LookupKey(const Key& key) {
  RecordMap::iterator found = mdns_cache_.find(key);
  if (found != mdns_cache_.end()) {
    return found->second;
  }
  return NULL;
}

MDnsCache::UpdateType MDnsCache::UpdateDnsRecord(
    scoped_ptr<const RecordParsed> record) {
  Key cache_key = Key::CreateFor(record.get());

  // Ignore "goodbye" packets for records not in cache.
  if (record->ttl() == 0 && mdns_cache_.find(cache_key) == mdns_cache_.end())
    return NoChange;

  base::Time new_expiration = GetEffectiveExpiration(record.get());
  if (next_expiration_ != base::Time())
    new_expiration = std::min(new_expiration, next_expiration_);

  std::pair<RecordMap::iterator, bool> insert_result =
      mdns_cache_.insert(std::make_pair(cache_key, (const RecordParsed*)NULL));
  UpdateType type = NoChange;
  if (insert_result.second) {
    type = RecordAdded;
  } else {
    const RecordParsed* other_record = insert_result.first->second;

    if (record->ttl() != 0 && !record->IsEqual(other_record, true)) {
      type = RecordChanged;
    }
    delete other_record;
  }

  insert_result.first->second = record.release();
  next_expiration_ = new_expiration;
  return type;
}

void MDnsCache::CleanupRecords(
    base::Time now,
    const RecordRemovedCallback& record_removed_callback) {
  base::Time next_expiration;

  // We are guaranteed that |next_expiration_| will be at or before the next
  // expiration. This allows clients to eagrely call CleanupRecords with
  // impunity.
  if (now < next_expiration_) return;

  for (RecordMap::iterator i = mdns_cache_.begin();
       i != mdns_cache_.end(); ) {
    base::Time expiration = GetEffectiveExpiration(i->second);
    if (now >= expiration) {
      record_removed_callback.Run(i->second);
      delete i->second;
      mdns_cache_.erase(i++);
    } else {
      if (next_expiration == base::Time() ||  expiration < next_expiration) {
        next_expiration = expiration;
      }
      ++i;
    }
  }

  next_expiration_ = next_expiration;
}

void MDnsCache::FindDnsRecords(unsigned type,
                               const std::string& name,
                               std::vector<const RecordParsed*>* results,
                               base::Time now) const {
  DCHECK(results);
  results->clear();

  RecordMap::const_iterator i = mdns_cache_.lower_bound(Key(type, name, ""));
  for (; i != mdns_cache_.end(); ++i) {
    if (i->first.name() != name ||
        (type != 0 && i->first.type() != type)) {
      break;
    }

    const RecordParsed* record = i->second;

    // Records are deleted only upon request.
    if (now >= GetEffectiveExpiration(record)) continue;

    results->push_back(record);
  }
}

scoped_ptr<const RecordParsed> MDnsCache::RemoveRecord(
    const RecordParsed* record) {
  Key key = Key::CreateFor(record);
  RecordMap::iterator found = mdns_cache_.find(key);

  if (found != mdns_cache_.end() && found->second == record) {
    mdns_cache_.erase(key);
    return scoped_ptr<const RecordParsed>(record);
  }

  return scoped_ptr<const RecordParsed>();
}

// static
std::string MDnsCache::GetOptionalFieldForRecord(
    const RecordParsed* record) {
  switch (record->type()) {
    case PtrRecordRdata::kType: {
      const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>();
      return rdata->ptrdomain();
    }
    default:  // Most records are considered unique for our purposes
      return "";
  }
}

// static
base::Time MDnsCache::GetEffectiveExpiration(const RecordParsed* record) {
  base::TimeDelta ttl;

  if (record->ttl()) {
    ttl = base::TimeDelta::FromSeconds(record->ttl());
  } else {
    ttl = base::TimeDelta::FromSeconds(kZeroTTLSeconds);
  }

  return record->time_created() + ttl;
}

}  // namespace net
