blob: 8150352c256e1d12ac996d95a26745cc880da697 [file] [log] [blame]
Peter Qiuc0beca52015-09-03 11:25:46 -07001//
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//
Peter Qiud670d032014-06-03 15:04:43 -070016
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
32using base::Bind;
33using base::Callback;
34using std::vector;
35using std::string;
36
37namespace shill {
38
39// static
40const char DNSServerTester::kDNSTestHostname[] = "www.gstatic.com";
41// static
42const int DNSServerTester::kDNSTestRetryIntervalMilliseconds = 60000;
43// static
44const int DNSServerTester::kDNSTimeoutMilliseconds = 5000;
45
46DNSServerTester::DNSServerTester(ConnectionRefPtr connection,
Paul Stewarta794cd62015-06-16 13:13:10 -070047 EventDispatcher* dispatcher,
48 const vector<string>& dns_servers,
Peter Qiud670d032014-06-03 15:04:43 -070049 const bool retry_until_success,
Paul Stewarta794cd62015-06-16 13:13:10 -070050 const Callback<void(const Status)>& callback)
Peter Qiud670d032014-06-03 15:04:43 -070051 : 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
66DNSServerTester::~DNSServerTester() {
67 Stop();
68}
69
70void DNSServerTester::Start() {
71 // Stop existing attempt.
72 Stop();
73 // Schedule the test to start immediately.
74 StartAttempt(0);
75}
76
77void 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
83void 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
92void DNSServerTester::Stop() {
93 start_attempt_.Cancel();
94 StopAttempt();
95}
96
97void DNSServerTester::StopAttempt() {
98 if (dns_test_client_.get()) {
99 dns_test_client_->Stop();
100 }
101}
102
103void 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
Paul Stewarta794cd62015-06-16 13:13:10 -0700113void DNSServerTester::DNSClientCallback(const Error& error,
Peter Qiud670d032014-06-03 15:04:43 -0700114 const IPAddress& ip) {
115 Status status = kStatusSuccess;
116 if (!error.IsSuccess()) {
117 status = kStatusFailure;
118 }
119
120 CompleteAttempt(status);
121}
122
123} // namespace shill