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 "base/stl_util.h" | |
8 #include "base/strings/string_number_conversions.h" | |
9 #include "net/dns/dns_protocol.h" | |
10 #include "net/dns/record_parsed.h" | |
11 #include "net/dns/record_rdata.h" | |
12 | |
13 // TODO(noamsml): Recursive CNAME closure (backwards and forwards). | |
14 | |
15 namespace net { | |
16 | |
17 // The effective TTL given to records with a nominal zero TTL. | |
18 // Allows time for hosts to send updated records. | |
szym
2013/05/17 05:04:34
I suggest referring to RFC 6762 Section 10.1 here.
Noam Samuel
2013/05/17 22:26:05
Done.
| |
19 static const unsigned kZeroTTLSeconds = 1; | |
20 | |
21 MDnsCache::DnsRecordCacheKey::DnsRecordCacheKey(unsigned type, | |
22 const std::string& name, | |
23 const std::string& optional) | |
24 : type_(type), name_(name), optional_(optional) { | |
25 } | |
26 | |
27 MDnsCache::DnsRecordCacheKey::~DnsRecordCacheKey() { | |
28 } | |
29 | |
30 bool MDnsCache::DnsRecordCacheKey::operator<( | |
31 const MDnsCache::DnsRecordCacheKey& key) const { | |
32 if (type_ != key.type_) | |
33 return type_ < key.type_; | |
34 | |
35 if (name_ != key.name_) | |
36 return name_ < key.name_; | |
37 | |
38 if (optional_ != key.optional_) | |
39 return optional_ < key.optional_; | |
40 return false; // keys are equal | |
41 } | |
42 | |
43 bool MDnsCache::DnsRecordCacheKey::operator==( | |
44 const MDnsCache::DnsRecordCacheKey& key) const { | |
45 return type_ == key.type_ && name_ == key.name_ && optional_ == key.optional_; | |
46 } | |
47 | |
48 MDnsCache::MDnsCache( | |
49 const MDnsCache::RecordRemovedCallback& record_removed_callback) | |
50 : record_removed_callback_(record_removed_callback) { | |
51 } | |
52 | |
53 MDnsCache::~MDnsCache() { | |
54 Clear(); | |
55 } | |
56 | |
57 void MDnsCache::Clear() { | |
58 next_expiration_ = base::Time(); | |
59 STLDeleteValues(&mdns_cache_); | |
60 } | |
61 | |
62 MDnsCache::UpdateType MDnsCache::UpdateDnsRecord( | |
63 scoped_ptr<const RecordParsed> record) { | |
64 UpdateType type = NoChange; | |
65 | |
66 MDnsCache::DnsRecordCacheKey cache_key = MDnsCache::DnsRecordCacheKey( | |
67 record->type(), | |
68 record->name(), | |
69 GetOptionalFieldForRecord(record.get())); | |
70 | |
71 base::Time expiration = GetEffectiveExpiration(record.get()); | |
72 if (next_expiration_ == base::Time() || expiration < next_expiration_) { | |
73 next_expiration_ = expiration; | |
74 } | |
75 | |
76 MDnsCacheMap::iterator i = mdns_cache_.find(cache_key); | |
szym
2013/05/17 05:04:34
I'd suggest:
const RecordParsed*& found = mdns_ca
Noam Samuel
2013/05/17 22:26:05
Done.
| |
77 if (i != mdns_cache_.end()) { | |
78 if (!record->IsEqual(i->second, true)) { | |
79 type = RecordChanged; | |
szym
2013/05/17 05:04:34
IMPORTANT: There is no RecordParsed::IsEqual.
Noam Samuel
2013/05/17 22:26:05
Oh whoops. Uploaded the patch wrong. This upload i
| |
80 } | |
81 delete i->second; | |
82 i->second = record.release(); | |
83 } else { | |
84 mdns_cache_[cache_key] = record.release(); | |
85 type = RecordAdded; | |
86 } | |
87 | |
88 return type; | |
89 } | |
90 | |
91 void MDnsCache::CleanupRecords( | |
szym
2013/05/17 05:04:34
nit: fits on a single line.
Noam Samuel
2013/05/17 22:26:05
Done.
| |
92 base::Time now) { | |
93 base::Time next_expiration; | |
94 | |
95 // We are guaranteed that next_expiration_ will be at or before the next | |
szym
2013/05/17 05:04:34
nit: || around variable names.
Noam Samuel
2013/05/17 22:26:05
Done.
| |
96 // expiration. This allows clients to eagrely call CleanupRecords with | |
97 // impunity. | |
98 if (now < next_expiration_) return; | |
99 | |
100 std::vector<MDnsCacheMap::iterator> to_delete; | |
szym
2013/05/17 05:04:34
Instead of keeping a handle on the iterators, remo
Noam Samuel
2013/05/17 22:26:05
Done.
| |
101 for (MDnsCacheMap::iterator i = mdns_cache_.begin(); | |
102 i != mdns_cache_.end(); i++) { | |
103 base::Time expiration = GetEffectiveExpiration(i->second); | |
104 if (now >= expiration) { | |
105 to_delete.push_back(i); | |
106 } else { | |
107 if (next_expiration == base::Time() || expiration < next_expiration) { | |
108 next_expiration = expiration; | |
109 } | |
110 } | |
111 } | |
112 | |
113 for (std::vector<MDnsCacheMap::iterator>::iterator i = to_delete.begin(); | |
114 i != to_delete.end(); ++i) { | |
115 record_removed_callback_.Run((*i)->second); | |
116 delete (*i)->second; | |
117 mdns_cache_.erase(*i); | |
118 } | |
119 | |
120 next_expiration_ = next_expiration; | |
121 } | |
122 | |
123 void MDnsCache::FindDnsRecords(unsigned type, | |
124 const std::string& name, | |
125 std::vector<const RecordParsed*>* results, | |
126 base::Time now) { | |
127 results->clear(); | |
szym
2013/05/17 05:04:34
DCHECK(results)
Noam Samuel
2013/05/17 22:26:05
Done.
| |
128 | |
129 MDnsCacheMap::iterator i = | |
130 mdns_cache_.lower_bound(DnsRecordCacheKey(type, name, "")); | |
131 for (; i != mdns_cache_.end(); ++i) { | |
132 if (i->first.type() != type || | |
133 (!name.empty() && i->first.name() != name)) { | |
134 break; | |
135 } | |
136 | |
137 const RecordParsed* record = i->second; | |
138 | |
139 // Records are deleted only upon request to make this op idempotent | |
140 if (now >= GetEffectiveExpiration(record)) continue; | |
141 | |
142 results->push_back(record); | |
143 } | |
144 } | |
145 | |
146 std::string MDnsCache::GetOptionalFieldForRecord(const RecordParsed* record) { | |
147 switch (record->type()) { | |
148 case PtrRecordRdata::kType: { | |
149 const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>(); | |
150 return rdata->ptrdomain(); | |
151 } | |
152 default: // Most records are considered unique for our purposes | |
153 return ""; | |
154 } | |
155 } | |
156 | |
157 base::Time MDnsCache::GetEffectiveExpiration(const RecordParsed* record) { | |
158 base::TimeDelta ttl; | |
159 | |
160 if (record->ttl()) { | |
161 ttl = base::TimeDelta::FromSeconds(record->ttl()); | |
162 } else { | |
163 ttl = base::TimeDelta::FromSeconds(kZeroTTLSeconds); | |
164 } | |
165 | |
166 return record->time_created() + ttl; | |
167 } | |
168 | |
169 } // namespace net | |
OLD | NEW |