summaryrefslogtreecommitdiffstats
path: root/net/dns/dns_config_service.cc
blob: dcf58bd3b466f5dd44c36a7d3827b6c54380ed5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/dns/dns_config_service.h"

#include "base/file_util.h"
#include "net/base/ip_endpoint.h"

namespace net {

// Default values are taken from glibc resolv.h.
DnsConfig::DnsConfig()
  : ndots(1),
    timeout(base::TimeDelta::FromSeconds(5)),
    attempts(2),
    rotate(false),
    edns0(false) {}

DnsConfig::~DnsConfig() {}

bool DnsConfig::EqualsIgnoreHosts(const DnsConfig& d) const {
  return (nameservers == d.nameservers) &&
         (search == d.search) &&
         (ndots == d.ndots) &&
         (timeout == d.timeout) &&
         (attempts == d.attempts) &&
         (rotate == d.rotate) &&
         (edns0 == d.edns0);
}

bool DnsConfig::Equals(const DnsConfig& d) const {
  return EqualsIgnoreHosts(d) && (hosts == d.hosts);
}

DnsConfigService::DnsConfigService()
  : have_config_(false),
    have_hosts_(false) {}

DnsConfigService::~DnsConfigService() {}

void DnsConfigService::AddObserver(Observer* observer) {
  DCHECK(CalledOnValidThread());
  observers_.AddObserver(observer);
  if (have_config_ && have_hosts_) {
    observer->OnConfigChanged(dns_config_);
  }
}

void DnsConfigService::RemoveObserver(Observer* observer) {
  DCHECK(CalledOnValidThread());
  observers_.RemoveObserver(observer);
}

void DnsConfigService::OnConfigRead(const DnsConfig& config) {
  DCHECK(CalledOnValidThread());
  if (!config.EqualsIgnoreHosts(dns_config_)) {
    DnsHosts current_hosts = dns_config_.hosts;
    dns_config_ = config;
    dns_config_.hosts.swap(current_hosts);
    have_config_ = true;
    if (have_hosts_) {
      FOR_EACH_OBSERVER(Observer, observers_, OnConfigChanged(dns_config_));
    }
  }
}

void DnsConfigService::OnHostsRead(const DnsHosts& hosts) {
  DCHECK(CalledOnValidThread());
  if (hosts != dns_config_.hosts || !have_hosts_) {
    dns_config_.hosts = hosts;
    have_hosts_ = true;
    if (have_config_) {
      FOR_EACH_OBSERVER(Observer, observers_, OnConfigChanged(dns_config_));
    }
  }
}

DnsHostsReader::DnsHostsReader(const FilePath& path, DnsConfigService* service)
  : path_(path),
    service_(service),
    success_(false) {
  DCHECK(service);
}

// Reads the contents of the file at |path| into |str| if the total length is
// less than |size|.
static bool ReadFile(const FilePath& path, int64 size, std::string* str) {
  int64 sz;
  if (!file_util::GetFileSize(path, &sz) || sz > size)
    return false;
  return file_util::ReadFileToString(path, str);
}

void DnsHostsReader::DoWork() {
  success_ = false;
  std::string contents;
  const int64 kMaxHostsSize = 1 << 16;
  if (ReadFile(path_, kMaxHostsSize, &contents)) {
    success_ = true;
    ParseHosts(contents, &dns_hosts_);
  }
}

void DnsHostsReader::OnWorkFinished() {
  DCHECK(!IsCancelled());
  if (success_)
    service_->OnHostsRead(dns_hosts_);
}

DnsHostsReader::~DnsHostsReader() {}

}  // namespace net