OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <stdio.h> | 5 #include <stdio.h> |
6 #include <string> | 6 #include <string> |
7 | 7 |
8 #include "base/at_exit.h" | 8 #include "base/at_exit.h" |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/cancelable_callback.h" | 10 #include "base/cancelable_callback.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 output.append(dns_config.search[i] + " "); | 65 output.append(dns_config.search[i] + " "); |
66 } | 66 } |
67 output.append("\n"); | 67 output.append("\n"); |
68 | 68 |
69 for (size_t i = 0; i < dns_config.nameservers.size(); ++i) { | 69 for (size_t i = 0; i < dns_config.nameservers.size(); ++i) { |
70 output.append("nameserver "); | 70 output.append("nameserver "); |
71 output.append(dns_config.nameservers[i].ToString()).append("\n"); | 71 output.append(dns_config.nameservers[i].ToString()).append("\n"); |
72 } | 72 } |
73 | 73 |
74 base::StringAppendF(&output, "options ndots:%d\n", dns_config.ndots); | 74 base::StringAppendF(&output, "options ndots:%d\n", dns_config.ndots); |
75 base::StringAppendF(&output, "options timeout:%d\n", | 75 base::StringAppendF(&output, |
| 76 "options timeout:%d\n", |
76 static_cast<int>(dns_config.timeout.InMilliseconds())); | 77 static_cast<int>(dns_config.timeout.InMilliseconds())); |
77 base::StringAppendF(&output, "options attempts:%d\n", dns_config.attempts); | 78 base::StringAppendF(&output, "options attempts:%d\n", dns_config.attempts); |
78 if (dns_config.rotate) | 79 if (dns_config.rotate) |
79 output.append("options rotate\n"); | 80 output.append("options rotate\n"); |
80 if (dns_config.edns0) | 81 if (dns_config.edns0) |
81 output.append("options edns0\n"); | 82 output.append("options edns0\n"); |
82 return output; | 83 return output; |
83 } | 84 } |
84 | 85 |
85 // Convert DnsConfig hosts member to a human readable text. | 86 // Convert DnsConfig hosts member to a human readable text. |
86 std::string DnsHostsToString(const DnsHosts& dns_hosts) { | 87 std::string DnsHostsToString(const DnsHosts& dns_hosts) { |
87 std::string output; | 88 std::string output; |
88 for (DnsHosts::const_iterator i = dns_hosts.begin(); | 89 for (DnsHosts::const_iterator i = dns_hosts.begin(); i != dns_hosts.end(); |
89 i != dns_hosts.end(); | |
90 ++i) { | 90 ++i) { |
91 const DnsHostsKey& key = i->first; | 91 const DnsHostsKey& key = i->first; |
92 std::string host_name = key.first; | 92 std::string host_name = key.first; |
93 output.append(IPEndPoint(i->second, -1).ToStringWithoutPort()); | 93 output.append(IPEndPoint(i->second, -1).ToStringWithoutPort()); |
94 output.append(" ").append(host_name).append("\n"); | 94 output.append(" ").append(host_name).append("\n"); |
95 } | 95 } |
96 return output; | 96 return output; |
97 } | 97 } |
98 | 98 |
99 struct ReplayLogEntry { | 99 struct ReplayLogEntry { |
(...skipping 11 matching lines...) Expand all Loading... |
111 // | 111 // |
112 // timestamp_in_milliseconds domain_name | 112 // timestamp_in_milliseconds domain_name |
113 // | 113 // |
114 // The timestamp_in_milliseconds needs to be an integral delta from start of | 114 // The timestamp_in_milliseconds needs to be an integral delta from start of |
115 // resolution and is in milliseconds. domain_name is the name to be resolved. | 115 // resolution and is in milliseconds. domain_name is the name to be resolved. |
116 // | 116 // |
117 // The file should be sorted by timestamp in ascending time. | 117 // The file should be sorted by timestamp in ascending time. |
118 bool LoadReplayLog(const base::FilePath& file_path, ReplayLog* replay_log) { | 118 bool LoadReplayLog(const base::FilePath& file_path, ReplayLog* replay_log) { |
119 std::string original_replay_log_contents; | 119 std::string original_replay_log_contents; |
120 if (!base::ReadFileToString(file_path, &original_replay_log_contents)) { | 120 if (!base::ReadFileToString(file_path, &original_replay_log_contents)) { |
121 fprintf(stderr, "Unable to open replay file %s\n", | 121 fprintf(stderr, |
| 122 "Unable to open replay file %s\n", |
122 file_path.MaybeAsASCII().c_str()); | 123 file_path.MaybeAsASCII().c_str()); |
123 return false; | 124 return false; |
124 } | 125 } |
125 | 126 |
126 // Strip out \r characters for Windows files. This isn't as efficient as a | 127 // Strip out \r characters for Windows files. This isn't as efficient as a |
127 // smarter line splitter, but this particular use does not need to target | 128 // smarter line splitter, but this particular use does not need to target |
128 // efficiency. | 129 // efficiency. |
129 std::string replay_log_contents; | 130 std::string replay_log_contents; |
130 base::RemoveChars(original_replay_log_contents, "\r", &replay_log_contents); | 131 base::RemoveChars(original_replay_log_contents, "\r", &replay_log_contents); |
131 | 132 |
(...skipping 23 matching lines...) Expand all Loading... |
155 "[%s %u] replay log should have format 'timestamp domain_name\\n'\n", | 156 "[%s %u] replay log should have format 'timestamp domain_name\\n'\n", |
156 file_path.MaybeAsASCII().c_str(), | 157 file_path.MaybeAsASCII().c_str(), |
157 i + 1); | 158 i + 1); |
158 bad_parse = true; | 159 bad_parse = true; |
159 continue; | 160 continue; |
160 } | 161 } |
161 | 162 |
162 base::TimeDelta delta = | 163 base::TimeDelta delta = |
163 base::TimeDelta::FromMilliseconds(delta_in_milliseconds); | 164 base::TimeDelta::FromMilliseconds(delta_in_milliseconds); |
164 if (delta < previous_delta) { | 165 if (delta < previous_delta) { |
165 fprintf( | 166 fprintf(stderr, |
166 stderr, | 167 "[%s %u] replay log should be sorted by time\n", |
167 "[%s %u] replay log should be sorted by time\n", | 168 file_path.MaybeAsASCII().c_str(), |
168 file_path.MaybeAsASCII().c_str(), | 169 i + 1); |
169 i + 1); | |
170 bad_parse = true; | 170 bad_parse = true; |
171 continue; | 171 continue; |
172 } | 172 } |
173 | 173 |
174 previous_delta = delta; | 174 previous_delta = delta; |
175 ReplayLogEntry entry; | 175 ReplayLogEntry entry; |
176 entry.start_time = delta; | 176 entry.start_time = delta; |
177 entry.domain_name = time_and_name[1]; | 177 entry.domain_name = time_and_name[1]; |
178 replay_log->push_back(entry); | 178 replay_log->push_back(entry); |
179 } | 179 } |
(...skipping 15 matching lines...) Expand all Loading... |
195 | 195 |
196 Result Main(int argc, const char* argv[]); | 196 Result Main(int argc, const char* argv[]); |
197 | 197 |
198 private: | 198 private: |
199 bool ParseCommandLine(int argc, const char* argv[]); | 199 bool ParseCommandLine(int argc, const char* argv[]); |
200 | 200 |
201 void Start(); | 201 void Start(); |
202 void Finish(Result); | 202 void Finish(Result); |
203 | 203 |
204 void OnDnsConfig(const DnsConfig& dns_config_const); | 204 void OnDnsConfig(const DnsConfig& dns_config_const); |
205 void OnResolveComplete(unsigned index, AddressList* address_list, | 205 void OnResolveComplete(unsigned index, |
206 base::TimeDelta time_since_start, int val); | 206 AddressList* address_list, |
| 207 base::TimeDelta time_since_start, |
| 208 int val); |
207 void OnTimeout(); | 209 void OnTimeout(); |
208 void ReplayNextEntry(); | 210 void ReplayNextEntry(); |
209 | 211 |
210 base::TimeDelta config_timeout_; | 212 base::TimeDelta config_timeout_; |
211 bool print_config_; | 213 bool print_config_; |
212 bool print_hosts_; | 214 bool print_hosts_; |
213 net::IPEndPoint nameserver_; | 215 net::IPEndPoint nameserver_; |
214 base::TimeDelta timeout_; | 216 base::TimeDelta timeout_; |
215 int parallellism_; | 217 int parallellism_; |
216 ReplayLog replay_log_; | 218 ReplayLog replay_log_; |
(...skipping 26 matching lines...) Expand all Loading... |
243 active_resolves_(0) { | 245 active_resolves_(0) { |
244 } | 246 } |
245 | 247 |
246 GDig::~GDig() { | 248 GDig::~GDig() { |
247 if (log_) | 249 if (log_) |
248 log_->RemoveThreadSafeObserver(log_observer_.get()); | 250 log_->RemoveThreadSafeObserver(log_observer_.get()); |
249 } | 251 } |
250 | 252 |
251 GDig::Result GDig::Main(int argc, const char* argv[]) { | 253 GDig::Result GDig::Main(int argc, const char* argv[]) { |
252 if (!ParseCommandLine(argc, argv)) { | 254 if (!ParseCommandLine(argc, argv)) { |
253 fprintf(stderr, | 255 fprintf(stderr, |
254 "usage: %s [--net_log[=<basic|no_bytes|all>]]" | 256 "usage: %s [--net_log[=<basic|no_bytes|all>]]" |
255 " [--print_config] [--print_hosts]" | 257 " [--print_config] [--print_hosts]" |
256 " [--nameserver=<ip_address[:port]>]" | 258 " [--nameserver=<ip_address[:port]>]" |
257 " [--timeout=<milliseconds>]" | 259 " [--timeout=<milliseconds>]" |
258 " [--config_timeout=<seconds>]" | 260 " [--config_timeout=<seconds>]" |
259 " [--j=<parallel resolves>]" | 261 " [--j=<parallel resolves>]" |
260 " [--replay_file=<path>]" | 262 " [--replay_file=<path>]" |
261 " [domain_name]\n", | 263 " [domain_name]\n", |
262 argv[0]); | 264 argv[0]); |
263 return RESULT_WRONG_USAGE; | 265 return RESULT_WRONG_USAGE; |
264 } | 266 } |
265 | 267 |
266 base::MessageLoopForIO loop; | 268 base::MessageLoopForIO loop; |
267 | 269 |
268 result_ = RESULT_PENDING; | 270 result_ = RESULT_PENDING; |
269 Start(); | 271 Start(); |
270 if (result_ == RESULT_PENDING) | 272 if (result_ == RESULT_PENDING) |
271 base::MessageLoop::current()->Run(); | 273 base::MessageLoop::current()->Run(); |
272 | 274 |
273 // Destroy it while MessageLoopForIO is alive. | 275 // Destroy it while MessageLoopForIO is alive. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 log_.reset(new NetLog); | 313 log_.reset(new NetLog); |
312 log_observer_.reset(new FileNetLogObserver(stderr)); | 314 log_observer_.reset(new FileNetLogObserver(stderr)); |
313 log_->AddThreadSafeObserver(log_observer_.get(), level); | 315 log_->AddThreadSafeObserver(log_observer_.get(), level); |
314 } | 316 } |
315 | 317 |
316 print_config_ = parsed_command_line.HasSwitch("print_config"); | 318 print_config_ = parsed_command_line.HasSwitch("print_config"); |
317 print_hosts_ = parsed_command_line.HasSwitch("print_hosts"); | 319 print_hosts_ = parsed_command_line.HasSwitch("print_hosts"); |
318 | 320 |
319 if (parsed_command_line.HasSwitch("nameserver")) { | 321 if (parsed_command_line.HasSwitch("nameserver")) { |
320 std::string nameserver = | 322 std::string nameserver = |
321 parsed_command_line.GetSwitchValueASCII("nameserver"); | 323 parsed_command_line.GetSwitchValueASCII("nameserver"); |
322 if (!StringToIPEndPoint(nameserver, &nameserver_)) { | 324 if (!StringToIPEndPoint(nameserver, &nameserver_)) { |
323 fprintf(stderr, | 325 fprintf(stderr, |
324 "Cannot parse the namerserver string into an IPEndPoint\n"); | 326 "Cannot parse the namerserver string into an IPEndPoint\n"); |
325 return false; | 327 return false; |
326 } | 328 } |
327 } | 329 } |
328 | 330 |
329 if (parsed_command_line.HasSwitch("timeout")) { | 331 if (parsed_command_line.HasSwitch("timeout")) { |
330 int timeout_millis = 0; | 332 int timeout_millis = 0; |
331 bool parsed = base::StringToInt( | 333 bool parsed = base::StringToInt( |
332 parsed_command_line.GetSwitchValueASCII("timeout"), | 334 parsed_command_line.GetSwitchValueASCII("timeout"), &timeout_millis); |
333 &timeout_millis); | |
334 if (parsed && timeout_millis > 0) { | 335 if (parsed && timeout_millis > 0) { |
335 timeout_ = base::TimeDelta::FromMilliseconds(timeout_millis); | 336 timeout_ = base::TimeDelta::FromMilliseconds(timeout_millis); |
336 } else { | 337 } else { |
337 fprintf(stderr, "Invalid timeout parameter\n"); | 338 fprintf(stderr, "Invalid timeout parameter\n"); |
338 return false; | 339 return false; |
339 } | 340 } |
340 } | 341 } |
341 | 342 |
342 if (parsed_command_line.HasSwitch("replay_file")) { | 343 if (parsed_command_line.HasSwitch("replay_file")) { |
343 base::FilePath replay_path = | 344 base::FilePath replay_path = |
344 parsed_command_line.GetSwitchValuePath("replay_file"); | 345 parsed_command_line.GetSwitchValuePath("replay_file"); |
345 if (!LoadReplayLog(replay_path, &replay_log_)) | 346 if (!LoadReplayLog(replay_path, &replay_log_)) |
346 return false; | 347 return false; |
347 } | 348 } |
348 | 349 |
349 if (parsed_command_line.HasSwitch("j")) { | 350 if (parsed_command_line.HasSwitch("j")) { |
350 int parallellism = 0; | 351 int parallellism = 0; |
351 bool parsed = base::StringToInt( | 352 bool parsed = base::StringToInt( |
352 parsed_command_line.GetSwitchValueASCII("j"), | 353 parsed_command_line.GetSwitchValueASCII("j"), ¶llellism); |
353 ¶llellism); | |
354 if (parsed && parallellism > 0) { | 354 if (parsed && parallellism > 0) { |
355 parallellism_ = parallellism; | 355 parallellism_ = parallellism; |
356 } else { | 356 } else { |
357 fprintf(stderr, "Invalid parallellism parameter\n"); | 357 fprintf(stderr, "Invalid parallellism parameter\n"); |
358 } | 358 } |
359 } | 359 } |
360 | 360 |
361 if (parsed_command_line.GetArgs().size() == 1) { | 361 if (parsed_command_line.GetArgs().size() == 1) { |
362 ReplayLogEntry entry; | 362 ReplayLogEntry entry; |
363 entry.start_time = base::TimeDelta(); | 363 entry.start_time = base::TimeDelta(); |
(...skipping 10 matching lines...) Expand all Loading... |
374 } | 374 } |
375 | 375 |
376 void GDig::Start() { | 376 void GDig::Start() { |
377 if (nameserver_.address().size() > 0) { | 377 if (nameserver_.address().size() > 0) { |
378 DnsConfig dns_config; | 378 DnsConfig dns_config; |
379 dns_config.attempts = 1; | 379 dns_config.attempts = 1; |
380 dns_config.nameservers.push_back(nameserver_); | 380 dns_config.nameservers.push_back(nameserver_); |
381 OnDnsConfig(dns_config); | 381 OnDnsConfig(dns_config); |
382 } else { | 382 } else { |
383 dns_config_service_ = DnsConfigService::CreateSystemService(); | 383 dns_config_service_ = DnsConfigService::CreateSystemService(); |
384 dns_config_service_->ReadConfig(base::Bind(&GDig::OnDnsConfig, | 384 dns_config_service_->ReadConfig( |
385 base::Unretained(this))); | 385 base::Bind(&GDig::OnDnsConfig, base::Unretained(this))); |
386 timeout_closure_.Reset(base::Bind(&GDig::OnTimeout, | 386 timeout_closure_.Reset( |
387 base::Unretained(this))); | 387 base::Bind(&GDig::OnTimeout, base::Unretained(this))); |
388 base::MessageLoop::current()->PostDelayedTask( | 388 base::MessageLoop::current()->PostDelayedTask( |
389 FROM_HERE, timeout_closure_.callback(), config_timeout_); | 389 FROM_HERE, timeout_closure_.callback(), config_timeout_); |
390 } | 390 } |
391 } | 391 } |
392 | 392 |
393 void GDig::Finish(Result result) { | 393 void GDig::Finish(Result result) { |
394 DCHECK_NE(RESULT_PENDING, result); | 394 DCHECK_NE(RESULT_PENDING, result); |
395 result_ = result; | 395 result_ = result; |
396 if (base::MessageLoop::current()) | 396 if (base::MessageLoop::current()) |
397 base::MessageLoop::current()->Quit(); | 397 base::MessageLoop::current()->Quit(); |
398 } | 398 } |
399 | 399 |
400 void GDig::OnDnsConfig(const DnsConfig& dns_config_const) { | 400 void GDig::OnDnsConfig(const DnsConfig& dns_config_const) { |
401 timeout_closure_.Cancel(); | 401 timeout_closure_.Cancel(); |
402 DCHECK(dns_config_const.IsValid()); | 402 DCHECK(dns_config_const.IsValid()); |
403 DnsConfig dns_config = dns_config_const; | 403 DnsConfig dns_config = dns_config_const; |
404 | 404 |
405 if (timeout_.InMilliseconds() > 0) | 405 if (timeout_.InMilliseconds() > 0) |
406 dns_config.timeout = timeout_; | 406 dns_config.timeout = timeout_; |
407 if (print_config_) { | 407 if (print_config_) { |
408 printf("# Dns Configuration\n" | 408 printf( |
409 "%s", DnsConfigToString(dns_config).c_str()); | 409 "# Dns Configuration\n" |
| 410 "%s", |
| 411 DnsConfigToString(dns_config).c_str()); |
410 } | 412 } |
411 if (print_hosts_) { | 413 if (print_hosts_) { |
412 printf("# Host Database\n" | 414 printf( |
413 "%s", DnsHostsToString(dns_config.hosts).c_str()); | 415 "# Host Database\n" |
| 416 "%s", |
| 417 DnsHostsToString(dns_config.hosts).c_str()); |
414 } | 418 } |
415 | 419 |
416 if (replay_log_.empty()) { | 420 if (replay_log_.empty()) { |
417 Finish(RESULT_OK); | 421 Finish(RESULT_OK); |
418 return; | 422 return; |
419 } | 423 } |
420 | 424 |
421 scoped_ptr<DnsClient> dns_client(DnsClient::CreateClient(NULL)); | 425 scoped_ptr<DnsClient> dns_client(DnsClient::CreateClient(NULL)); |
422 dns_client->SetConfig(dns_config); | 426 dns_client->SetConfig(dns_config); |
423 scoped_ptr<HostResolverImpl> resolver( | 427 scoped_ptr<HostResolverImpl> resolver(new HostResolverImpl( |
424 new HostResolverImpl( | 428 HostCache::CreateDefaultCache(), |
425 HostCache::CreateDefaultCache(), | 429 PrioritizedDispatcher::Limits(NUM_PRIORITIES, parallellism_), |
426 PrioritizedDispatcher::Limits(NUM_PRIORITIES, parallellism_), | 430 HostResolverImpl::ProcTaskParams(NULL, 1), |
427 HostResolverImpl::ProcTaskParams(NULL, 1), | 431 log_.get())); |
428 log_.get())); | |
429 resolver->SetDnsClient(dns_client.Pass()); | 432 resolver->SetDnsClient(dns_client.Pass()); |
430 resolver_ = resolver.Pass(); | 433 resolver_ = resolver.Pass(); |
431 | 434 |
432 start_time_ = base::Time::Now(); | 435 start_time_ = base::Time::Now(); |
433 | 436 |
434 ReplayNextEntry(); | 437 ReplayNextEntry(); |
435 } | 438 } |
436 | 439 |
437 void GDig::ReplayNextEntry() { | 440 void GDig::ReplayNextEntry() { |
438 DCHECK_LT(replay_log_index_, replay_log_.size()); | 441 DCHECK_LT(replay_log_index_, replay_log_.size()); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 DCHECK_GT(active_resolves_, 0); | 481 DCHECK_GT(active_resolves_, 0); |
479 DCHECK(address_list); | 482 DCHECK(address_list); |
480 DCHECK_LT(entry_index, replay_log_.size()); | 483 DCHECK_LT(entry_index, replay_log_.size()); |
481 --active_resolves_; | 484 --active_resolves_; |
482 base::TimeDelta resolve_end_time = base::Time::Now() - start_time_; | 485 base::TimeDelta resolve_end_time = base::Time::Now() - start_time_; |
483 base::TimeDelta resolve_time = resolve_end_time - resolve_start_time; | 486 base::TimeDelta resolve_time = resolve_end_time - resolve_start_time; |
484 printf("%u %d %d %s %d ", | 487 printf("%u %d %d %s %d ", |
485 entry_index, | 488 entry_index, |
486 static_cast<int>(resolve_end_time.InMilliseconds()), | 489 static_cast<int>(resolve_end_time.InMilliseconds()), |
487 static_cast<int>(resolve_time.InMilliseconds()), | 490 static_cast<int>(resolve_time.InMilliseconds()), |
488 replay_log_[entry_index].domain_name.c_str(), val); | 491 replay_log_[entry_index].domain_name.c_str(), |
| 492 val); |
489 if (val != OK) { | 493 if (val != OK) { |
490 printf("%s", ErrorToString(val)); | 494 printf("%s", ErrorToString(val)); |
491 } else { | 495 } else { |
492 for (size_t i = 0; i < address_list->size(); ++i) { | 496 for (size_t i = 0; i < address_list->size(); ++i) { |
493 if (i != 0) | 497 if (i != 0) |
494 printf(" "); | 498 printf(" "); |
495 printf("%s", (*address_list)[i].ToStringWithoutPort().c_str()); | 499 printf("%s", (*address_list)[i].ToStringWithoutPort().c_str()); |
496 } | 500 } |
497 } | 501 } |
498 printf("\n"); | 502 printf("\n"); |
499 if (active_resolves_ == 0 && replay_log_index_ >= replay_log_.size()) | 503 if (active_resolves_ == 0 && replay_log_index_ >= replay_log_.size()) |
500 Finish(RESULT_OK); | 504 Finish(RESULT_OK); |
501 } | 505 } |
502 | 506 |
503 void GDig::OnTimeout() { | 507 void GDig::OnTimeout() { |
504 fprintf(stderr, "Timed out waiting to load the dns config\n"); | 508 fprintf(stderr, "Timed out waiting to load the dns config\n"); |
505 Finish(RESULT_NO_CONFIG); | 509 Finish(RESULT_NO_CONFIG); |
506 } | 510 } |
507 | 511 |
508 } // empty namespace | 512 } // empty namespace |
509 | 513 |
510 } // namespace net | 514 } // namespace net |
511 | 515 |
512 int main(int argc, const char* argv[]) { | 516 int main(int argc, const char* argv[]) { |
513 net::GDig dig; | 517 net::GDig dig; |
514 return dig.Main(argc, argv); | 518 return dig.Main(argc, argv); |
515 } | 519 } |
OLD | NEW |