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
|
require "time"
module AsyncDNS
class Settings
@local_domain : String?
@last_reload : Time?
getter :static_hosts, :name_servers, :local_domain, :search_domains,
:timeout, :max_attempts, :abs_num_dots, :uses_tcp
setter :static_hosts, :name_servers, :local_domain, :search_domains,
:uses_tcp
def initialize
@static_hosts = Hash(String, Array(String)).new
@name_servers = [] of String
@search_domains = [] of String
@timeout = Time::Span.new(seconds: 2)
@max_attempts = 2
@abs_num_dots = 1
@uses_tcp = false
self.reload
end
def reload
{% if flag?(:unix) %}
self.parse_hosts "/etc/hosts"
{% else %}
{% raise "Your OS is not supported by AsyncDNS" %}
{% end %}
end
def parse_hosts(path)
file = File.open(path, "r")
@static_hosts.clear
file.each_line do |line|
pos = line.index('#')
line = line[0, pos] if pos
split = line.split(/[ \t]/, remove_empty: true)
next unless split.size >= 2
address = split[0]
split[1, split.size - 1].each do |host|
addresses = @static_hosts[host]?
if addresses.nil?
addresses = [] of String
@static_hosts[host] = addresses
end
addresses << address
end
end
end
end
end
|
>
>
>
|
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
|
|
>
|
>
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
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
115
116
117
118
119
120
121
|
require "time"
module AsyncDNS
class Settings
@local_domain : String?
@reload_period : Time::Span
@last_reload : Time?
property static_hosts, nameservers, local_domain, search_domains, uses_tcp
getter timeout, max_attempts, abs_num_dots
def timeout=(timeout)
raise ArgumentError.new("timeout must be positive") if timeout < 0
@timeout = timeout
end
def max_attempts=(max_attempts)
if max_attempts < 0
raise ArgumentError.new("max_attempts must be positive")
end
@max_attempts = max_attempts
end
def abs_num_dots=(abs_num_dots)
if abs_num_dots < 0
raise ArgumentError.new("abs_num_dots must be positive")
end
@abs_num_dots = abs_num_dots
end
def initialize
@static_hosts = Hash(String, Array(String)).new
@nameservers = [] of String
@search_domains = [] of String
@timeout = Time::Span.new(seconds: 2)
@max_attempts = 3
@abs_num_dots = 1
@uses_tcp = false
@reload_period = Time::Span.new(seconds: 2)
self.reload
end
def reload
{% if flag?(:unix) %}
self.parse_hosts "/etc/hosts"
self.parse_resolv_conf "/etc/resolv.conf"
{% else %}
{% raise "Your OS is not supported by AsyncDNS" %}
{% end %}
end
def parse_hosts(path)
@static_hosts.clear
File.each_line(path, chomp: true) do |line|
pos = line.index('#')
line = line[0, pos] if pos
split = line.split(/[ \t]/, remove_empty: true)
next if split.size < 2
address = split[0]
split[1, split.size - 1].each do |host|
addresses = @static_hosts[host]?
if addresses.nil?
addresses = [] of String
@static_hosts[host] = addresses
end
addresses << address
end
end
end
def parse_resolv_conf(path)
@nameservers.clear
@local_domain = nil
@search_domains.clear
File.each_line(path, chomp: true) do |line|
pos = line.index(/[#;]/)
line = line[0, pos] if pos
split = line.split(/[ \t]/, remove_empty: true)
next if split.size < 2
case split[0]
when "nameserver"
next if split.size != 2
@nameservers << split[1]
when "domain"
next if split.size != 2
@local_domain = split[1]
when "search"
@search_domains = split[1, split.size - 1]
when "options"
split[1, split.size - 1].each { |option| parse_resolv_option(option) }
end
end
end
private def parse_resolv_option(option)
if option.starts_with?("ndots:")
@abs_num_dots = option[6, option.size - 6].to_i
elsif option.starts_with?("timeout:")
@timeout = Time::Span.new(seconds: option[8, option.size - 8].to_i)
elsif option.starts_with?("attempts:")
@max_attempts = option[9, option.size - 9].to_i
elsif option.starts_with?("reload-period:")
@reload_period = Time::Span.new(
seconds: option[14, option.size - 14].to_i)
elsif option = "tcp"
@uses_tcp = true
end
end
end
end
|