OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/dns/mdns_cache.h" | 5 #include "net/dns/mdns_cache.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "net/dns/dns_protocol.h" | 12 #include "net/dns/dns_protocol.h" |
13 #include "net/dns/record_parsed.h" | 13 #include "net/dns/record_parsed.h" |
14 #include "net/dns/record_rdata.h" | 14 #include "net/dns/record_rdata.h" |
15 | 15 |
16 // TODO(noamsml): Recursive CNAME closure (backwards and forwards). | 16 // TODO(noamsml): Recursive CNAME closure (backwards and forwards). |
17 | 17 |
18 namespace net { | 18 namespace net { |
19 | 19 |
20 // The effective TTL given to records with a nominal zero TTL. | 20 // The effective TTL given to records with a nominal zero TTL. |
21 // Allows time for hosts to send updated records, as detailed in RFC 6762 | 21 // Allows time for hosts to send updated records, as detailed in RFC 6762 |
22 // Section 10.1. | 22 // Section 10.1. |
23 static const unsigned kZeroTTLSeconds = 1; | 23 static const unsigned kZeroTTLSeconds = 1; |
24 | 24 |
25 MDnsCache::Key::Key(unsigned type, const std::string& name, | 25 MDnsCache::Key::Key(unsigned type, |
| 26 const std::string& name, |
26 const std::string& optional) | 27 const std::string& optional) |
27 : type_(type), name_(name), optional_(optional) { | 28 : type_(type), name_(name), optional_(optional) { |
28 } | 29 } |
29 | 30 |
30 MDnsCache::Key::Key( | 31 MDnsCache::Key::Key(const MDnsCache::Key& other) |
31 const MDnsCache::Key& other) | |
32 : type_(other.type_), name_(other.name_), optional_(other.optional_) { | 32 : type_(other.type_), name_(other.name_), optional_(other.optional_) { |
33 } | 33 } |
34 | 34 |
35 | 35 MDnsCache::Key& MDnsCache::Key::operator=(const MDnsCache::Key& other) { |
36 MDnsCache::Key& MDnsCache::Key::operator=( | |
37 const MDnsCache::Key& other) { | |
38 type_ = other.type_; | 36 type_ = other.type_; |
39 name_ = other.name_; | 37 name_ = other.name_; |
40 optional_ = other.optional_; | 38 optional_ = other.optional_; |
41 return *this; | 39 return *this; |
42 } | 40 } |
43 | 41 |
44 MDnsCache::Key::~Key() { | 42 MDnsCache::Key::~Key() { |
45 } | 43 } |
46 | 44 |
47 bool MDnsCache::Key::operator<(const MDnsCache::Key& key) const { | 45 bool MDnsCache::Key::operator<(const MDnsCache::Key& key) const { |
48 if (name_ != key.name_) | 46 if (name_ != key.name_) |
49 return name_ < key.name_; | 47 return name_ < key.name_; |
50 | 48 |
51 if (type_ != key.type_) | 49 if (type_ != key.type_) |
52 return type_ < key.type_; | 50 return type_ < key.type_; |
53 | 51 |
54 if (optional_ != key.optional_) | 52 if (optional_ != key.optional_) |
55 return optional_ < key.optional_; | 53 return optional_ < key.optional_; |
56 return false; // keys are equal | 54 return false; // keys are equal |
57 } | 55 } |
58 | 56 |
59 bool MDnsCache::Key::operator==(const MDnsCache::Key& key) const { | 57 bool MDnsCache::Key::operator==(const MDnsCache::Key& key) const { |
60 return type_ == key.type_ && name_ == key.name_ && optional_ == key.optional_; | 58 return type_ == key.type_ && name_ == key.name_ && optional_ == key.optional_; |
61 } | 59 } |
62 | 60 |
63 // static | 61 // static |
64 MDnsCache::Key MDnsCache::Key::CreateFor(const RecordParsed* record) { | 62 MDnsCache::Key MDnsCache::Key::CreateFor(const RecordParsed* record) { |
65 return Key(record->type(), | 63 return Key(record->type(), record->name(), GetOptionalFieldForRecord(record)); |
66 record->name(), | |
67 GetOptionalFieldForRecord(record)); | |
68 } | 64 } |
69 | 65 |
70 | |
71 MDnsCache::MDnsCache() { | 66 MDnsCache::MDnsCache() { |
72 } | 67 } |
73 | 68 |
74 MDnsCache::~MDnsCache() { | 69 MDnsCache::~MDnsCache() { |
75 Clear(); | 70 Clear(); |
76 } | 71 } |
77 | 72 |
78 void MDnsCache::Clear() { | 73 void MDnsCache::Clear() { |
79 next_expiration_ = base::Time(); | 74 next_expiration_ = base::Time(); |
80 STLDeleteValues(&mdns_cache_); | 75 STLDeleteValues(&mdns_cache_); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 } | 115 } |
121 | 116 |
122 void MDnsCache::CleanupRecords( | 117 void MDnsCache::CleanupRecords( |
123 base::Time now, | 118 base::Time now, |
124 const RecordRemovedCallback& record_removed_callback) { | 119 const RecordRemovedCallback& record_removed_callback) { |
125 base::Time next_expiration; | 120 base::Time next_expiration; |
126 | 121 |
127 // We are guaranteed that |next_expiration_| will be at or before the next | 122 // We are guaranteed that |next_expiration_| will be at or before the next |
128 // expiration. This allows clients to eagrely call CleanupRecords with | 123 // expiration. This allows clients to eagrely call CleanupRecords with |
129 // impunity. | 124 // impunity. |
130 if (now < next_expiration_) return; | 125 if (now < next_expiration_) |
| 126 return; |
131 | 127 |
132 for (RecordMap::iterator i = mdns_cache_.begin(); | 128 for (RecordMap::iterator i = mdns_cache_.begin(); i != mdns_cache_.end();) { |
133 i != mdns_cache_.end(); ) { | |
134 base::Time expiration = GetEffectiveExpiration(i->second); | 129 base::Time expiration = GetEffectiveExpiration(i->second); |
135 if (now >= expiration) { | 130 if (now >= expiration) { |
136 record_removed_callback.Run(i->second); | 131 record_removed_callback.Run(i->second); |
137 delete i->second; | 132 delete i->second; |
138 mdns_cache_.erase(i++); | 133 mdns_cache_.erase(i++); |
139 } else { | 134 } else { |
140 if (next_expiration == base::Time() || expiration < next_expiration) { | 135 if (next_expiration == base::Time() || expiration < next_expiration) { |
141 next_expiration = expiration; | 136 next_expiration = expiration; |
142 } | 137 } |
143 ++i; | 138 ++i; |
144 } | 139 } |
145 } | 140 } |
146 | 141 |
147 next_expiration_ = next_expiration; | 142 next_expiration_ = next_expiration; |
148 } | 143 } |
149 | 144 |
150 void MDnsCache::FindDnsRecords(unsigned type, | 145 void MDnsCache::FindDnsRecords(unsigned type, |
151 const std::string& name, | 146 const std::string& name, |
152 std::vector<const RecordParsed*>* results, | 147 std::vector<const RecordParsed*>* results, |
153 base::Time now) const { | 148 base::Time now) const { |
154 DCHECK(results); | 149 DCHECK(results); |
155 results->clear(); | 150 results->clear(); |
156 | 151 |
157 RecordMap::const_iterator i = mdns_cache_.lower_bound(Key(type, name, "")); | 152 RecordMap::const_iterator i = mdns_cache_.lower_bound(Key(type, name, "")); |
158 for (; i != mdns_cache_.end(); ++i) { | 153 for (; i != mdns_cache_.end(); ++i) { |
159 if (i->first.name() != name || | 154 if (i->first.name() != name || (type != 0 && i->first.type() != type)) { |
160 (type != 0 && i->first.type() != type)) { | |
161 break; | 155 break; |
162 } | 156 } |
163 | 157 |
164 const RecordParsed* record = i->second; | 158 const RecordParsed* record = i->second; |
165 | 159 |
166 // Records are deleted only upon request. | 160 // Records are deleted only upon request. |
167 if (now >= GetEffectiveExpiration(record)) continue; | 161 if (now >= GetEffectiveExpiration(record)) |
| 162 continue; |
168 | 163 |
169 results->push_back(record); | 164 results->push_back(record); |
170 } | 165 } |
171 } | 166 } |
172 | 167 |
173 scoped_ptr<const RecordParsed> MDnsCache::RemoveRecord( | 168 scoped_ptr<const RecordParsed> MDnsCache::RemoveRecord( |
174 const RecordParsed* record) { | 169 const RecordParsed* record) { |
175 Key key = Key::CreateFor(record); | 170 Key key = Key::CreateFor(record); |
176 RecordMap::iterator found = mdns_cache_.find(key); | 171 RecordMap::iterator found = mdns_cache_.find(key); |
177 | 172 |
178 if (found != mdns_cache_.end() && found->second == record) { | 173 if (found != mdns_cache_.end() && found->second == record) { |
179 mdns_cache_.erase(key); | 174 mdns_cache_.erase(key); |
180 return scoped_ptr<const RecordParsed>(record); | 175 return scoped_ptr<const RecordParsed>(record); |
181 } | 176 } |
182 | 177 |
183 return scoped_ptr<const RecordParsed>(); | 178 return scoped_ptr<const RecordParsed>(); |
184 } | 179 } |
185 | 180 |
186 // static | 181 // static |
187 std::string MDnsCache::GetOptionalFieldForRecord( | 182 std::string MDnsCache::GetOptionalFieldForRecord(const RecordParsed* record) { |
188 const RecordParsed* record) { | |
189 switch (record->type()) { | 183 switch (record->type()) { |
190 case PtrRecordRdata::kType: { | 184 case PtrRecordRdata::kType: { |
191 const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>(); | 185 const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>(); |
192 return rdata->ptrdomain(); | 186 return rdata->ptrdomain(); |
193 } | 187 } |
194 default: // Most records are considered unique for our purposes | 188 default: // Most records are considered unique for our purposes |
195 return ""; | 189 return ""; |
196 } | 190 } |
197 } | 191 } |
198 | 192 |
199 // static | 193 // static |
200 base::Time MDnsCache::GetEffectiveExpiration(const RecordParsed* record) { | 194 base::Time MDnsCache::GetEffectiveExpiration(const RecordParsed* record) { |
201 base::TimeDelta ttl; | 195 base::TimeDelta ttl; |
202 | 196 |
203 if (record->ttl()) { | 197 if (record->ttl()) { |
204 ttl = base::TimeDelta::FromSeconds(record->ttl()); | 198 ttl = base::TimeDelta::FromSeconds(record->ttl()); |
205 } else { | 199 } else { |
206 ttl = base::TimeDelta::FromSeconds(kZeroTTLSeconds); | 200 ttl = base::TimeDelta::FromSeconds(kZeroTTLSeconds); |
207 } | 201 } |
208 | 202 |
209 return record->time_created() + ttl; | 203 return record->time_created() + ttl; |
210 } | 204 } |
211 | 205 |
212 } // namespace net | 206 } // namespace net |
OLD | NEW |