Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/dns/mdns_cache.h" | |
| 6 | |
| 7 #include <utility> | |
| 8 | |
| 9 #include "base/stl_util.h" | |
| 10 #include "base/strings/string_number_conversions.h" | |
| 11 #include "net/dns/dns_protocol.h" | |
| 12 #include "net/dns/record_parsed.h" | |
| 13 #include "net/dns/record_rdata.h" | |
| 14 | |
| 15 // TODO(noamsml): Recursive CNAME closure (backwards and forwards). | |
| 16 | |
| 17 namespace net { | |
| 18 | |
| 19 // The effective TTL given to records with a nominal zero TTL. | |
| 20 // Allows time for hosts to send updated records, as detailed in RFC 6762 | |
| 21 // Section 10.1. | |
| 22 static const unsigned kZeroTTLSeconds = 1; | |
| 23 | |
| 24 MDnsCache::Key::Key(unsigned type, const std::string& name, | |
| 25 const std::string& optional) | |
| 26 : type_(type), name_(name), optional_(optional) { | |
| 27 } | |
| 28 | |
| 29 MDnsCache::Key::Key( | |
| 30 const MDnsCache::Key& other) | |
| 31 : type_(other.type_), name_(other.name_), optional_(other.optional_) { | |
| 32 } | |
| 33 | |
| 34 | |
| 35 MDnsCache::Key& MDnsCache::Key::operator=( | |
| 36 const MDnsCache::Key& other) { | |
| 37 type_ = other.type_; | |
| 38 name_ = other.name_; | |
| 39 optional_ = other.optional_; | |
| 40 return *this; | |
| 41 } | |
| 42 | |
| 43 MDnsCache::Key::~Key() { | |
| 44 } | |
| 45 | |
| 46 bool MDnsCache::Key::operator<( | |
| 47 const MDnsCache::Key& key) const { | |
|
szym
2013/05/21 22:09:05
one line
Noam Samuel
2013/05/21 23:00:56
Done.
| |
| 48 if (type_ != key.type_) | |
| 49 return type_ < key.type_; | |
| 50 | |
| 51 if (name_ != key.name_) | |
| 52 return name_ < key.name_; | |
| 53 | |
| 54 if (optional_ != key.optional_) | |
| 55 return optional_ < key.optional_; | |
| 56 return false; // keys are equal | |
| 57 } | |
| 58 | |
| 59 bool MDnsCache::Key::operator==( | |
| 60 const MDnsCache::Key& key) const { | |
|
szym
2013/05/21 22:09:05
one line
szym
2013/05/21 22:09:05
one line
Noam Samuel
2013/05/21 23:00:56
Done.
| |
| 61 return type_ == key.type_ && name_ == key.name_ && optional_ == key.optional_; | |
| 62 } | |
| 63 | |
| 64 MDnsCache::MDnsCache() { | |
| 65 } | |
| 66 | |
| 67 MDnsCache::~MDnsCache() { | |
| 68 Clear(); | |
| 69 } | |
| 70 | |
| 71 void MDnsCache::Clear() { | |
| 72 next_expiration_ = base::Time(); | |
| 73 STLDeleteValues(&mdns_cache_); | |
| 74 } | |
| 75 | |
| 76 MDnsCache::UpdateType MDnsCache::UpdateDnsRecord( | |
| 77 scoped_ptr<const RecordParsed> record) { | |
| 78 UpdateType type = NoChange; | |
| 79 | |
| 80 MDnsCache::Key cache_key = MDnsCache::Key( | |
| 81 record->type(), | |
| 82 record->name(), | |
| 83 GetOptionalFieldForRecord(record.get())); | |
| 84 | |
| 85 base::Time expiration = GetEffectiveExpiration(record.get()); | |
| 86 if (next_expiration_ == base::Time() || expiration < next_expiration_) { | |
| 87 next_expiration_ = expiration; | |
| 88 } | |
| 89 | |
| 90 std::pair<RecordMap::iterator, bool> insert_result = | |
| 91 mdns_cache_.insert(std::make_pair(cache_key, (const RecordParsed*)NULL)); | |
| 92 | |
| 93 if (insert_result.second) { | |
| 94 type = RecordAdded; | |
| 95 insert_result.first->second = record.release(); | |
| 96 } else { | |
| 97 const RecordParsed* other_record = insert_result.first->second; | |
| 98 | |
| 99 if (!record->IsEqual(other_record, true)) { | |
| 100 type = RecordChanged; | |
| 101 } | |
| 102 delete other_record; | |
| 103 insert_result.first->second = record.release(); | |
| 104 } | |
| 105 | |
| 106 return type; | |
| 107 } | |
| 108 | |
| 109 void MDnsCache::CleanupRecords( | |
| 110 base::Time now, | |
| 111 const RecordRemovedCallback& record_removed_callback) { | |
| 112 base::Time next_expiration; | |
| 113 | |
| 114 // We are guaranteed that |next_expiration_| will be at or before the next | |
| 115 // expiration. This allows clients to eagrely call CleanupRecords with | |
| 116 // impunity. | |
| 117 if (now < next_expiration_) return; | |
| 118 | |
| 119 for (RecordMap::iterator i = mdns_cache_.begin(); | |
| 120 i != mdns_cache_.end(); ) { | |
| 121 base::Time expiration = GetEffectiveExpiration(i->second); | |
| 122 if (now >= expiration) { | |
| 123 record_removed_callback.Run(i->second); | |
| 124 delete i->second; | |
| 125 mdns_cache_.erase(i++); | |
| 126 } else { | |
| 127 if (next_expiration == base::Time() || expiration < next_expiration) { | |
| 128 next_expiration = expiration; | |
| 129 } | |
| 130 ++i; | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 next_expiration_ = next_expiration; | |
| 135 } | |
| 136 | |
| 137 void MDnsCache::FindDnsRecords(unsigned type, | |
| 138 const std::string& name, | |
| 139 std::vector<const RecordParsed*>* results, | |
| 140 base::Time now) const { | |
| 141 DCHECK(results); | |
| 142 results->clear(); | |
| 143 | |
| 144 RecordMap::const_iterator i = | |
| 145 mdns_cache_.lower_bound(Key(type, name, "")); | |
|
szym
2013/05/21 22:09:05
one line
Noam Samuel
2013/05/21 23:00:56
Done.
| |
| 146 for (; i != mdns_cache_.end(); ++i) { | |
| 147 if (i->first.type() != type || | |
| 148 (!name.empty() && i->first.name() != name)) { | |
| 149 break; | |
| 150 } | |
| 151 | |
| 152 const RecordParsed* record = i->second; | |
| 153 | |
| 154 // Records are deleted only upon request. | |
| 155 if (now >= GetEffectiveExpiration(record)) continue; | |
| 156 | |
| 157 results->push_back(record); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 std::string MDnsCache::GetOptionalFieldForRecord( | |
| 162 const RecordParsed* record) const { | |
| 163 switch (record->type()) { | |
| 164 case PtrRecordRdata::kType: { | |
| 165 const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>(); | |
| 166 return rdata->ptrdomain(); | |
| 167 } | |
| 168 default: // Most records are considered unique for our purposes | |
| 169 return ""; | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 base::Time MDnsCache::GetEffectiveExpiration(const RecordParsed* record) const { | |
| 174 base::TimeDelta ttl; | |
| 175 | |
| 176 if (record->ttl()) { | |
| 177 ttl = base::TimeDelta::FromSeconds(record->ttl()); | |
| 178 } else { | |
| 179 ttl = base::TimeDelta::FromSeconds(kZeroTTLSeconds); | |
| 180 } | |
| 181 | |
| 182 return record->time_created() + ttl; | |
| 183 } | |
| 184 | |
| 185 } // namespace net | |
| OLD | NEW |