1 // 2 // Copyright (C) 2014 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "shill/dns_server_tester.h" 18 19 #include <string> 20 21 #include <base/bind.h> 22 #include <base/strings/string_number_conversions.h> 23 #include <base/strings/string_util.h> 24 #include <base/strings/stringprintf.h> 25 26 #include "shill/connection.h" 27 #include "shill/dns_client.h" 28 #include "shill/dns_client_factory.h" 29 #include "shill/error.h" 30 #include "shill/event_dispatcher.h" 31 32 using base::Bind; 33 using base::Callback; 34 using std::vector; 35 using std::string; 36 37 namespace shill { 38 39 // static 40 const char DNSServerTester::kDNSTestHostname[] = "www.gstatic.com"; 41 // static 42 const int DNSServerTester::kDNSTestRetryIntervalMilliseconds = 60000; 43 // static 44 const int DNSServerTester::kDNSTimeoutMilliseconds = 5000; 45 46 DNSServerTester::DNSServerTester(ConnectionRefPtr connection, 47 EventDispatcher* dispatcher, 48 const vector<string>& dns_servers, 49 const bool retry_until_success, 50 const Callback<void(const Status)>& callback) 51 : connection_(connection), 52 dispatcher_(dispatcher), 53 retry_until_success_(retry_until_success), 54 weak_ptr_factory_(this), 55 dns_result_callback_(callback), 56 dns_client_callback_(Bind(&DNSServerTester::DNSClientCallback, 57 weak_ptr_factory_.GetWeakPtr())), 58 dns_test_client_(DNSClientFactory::GetInstance()->CreateDNSClient( 59 IPAddress::kFamilyIPv4, 60 connection_->interface_name(), 61 dns_servers, 62 kDNSTimeoutMilliseconds, 63 dispatcher_, 64 dns_client_callback_)) {} 65 66 DNSServerTester::~DNSServerTester() { 67 Stop(); 68 } 69 70 void DNSServerTester::Start() { 71 // Stop existing attempt. 72 Stop(); 73 // Schedule the test to start immediately. 74 StartAttempt(0); 75 } 76 77 void DNSServerTester::StartAttempt(int delay_ms) { 78 start_attempt_.Reset(Bind(&DNSServerTester::StartAttemptTask, 79 weak_ptr_factory_.GetWeakPtr())); 80 dispatcher_->PostDelayedTask(start_attempt_.callback(), delay_ms); 81 } 82 83 void DNSServerTester::StartAttemptTask() { 84 Error error; 85 if (!dns_test_client_->Start(kDNSTestHostname, &error)) { 86 LOG(ERROR) << __func__ << ": Failed to start DNS client " 87 << error.message(); 88 CompleteAttempt(kStatusFailure); 89 } 90 } 91 92 void DNSServerTester::Stop() { 93 start_attempt_.Cancel(); 94 StopAttempt(); 95 } 96 97 void DNSServerTester::StopAttempt() { 98 if (dns_test_client_.get()) { 99 dns_test_client_->Stop(); 100 } 101 } 102 103 void DNSServerTester::CompleteAttempt(Status status) { 104 if (status == kStatusFailure && retry_until_success_) { 105 // Schedule the test to restart after retry timeout interval. 106 StartAttempt(kDNSTestRetryIntervalMilliseconds); 107 return; 108 } 109 110 dns_result_callback_.Run(status); 111 } 112 113 void DNSServerTester::DNSClientCallback(const Error& error, 114 const IPAddress& ip) { 115 Status status = kStatusSuccess; 116 if (!error.IsSuccess()) { 117 status = kStatusFailure; 118 } 119 120 CompleteAttempt(status); 121 } 122 123 } // namespace shill 124