AsyncDNS-cr  Check-in [070b3339e0]

Overview
Comment:Parse resolv.conf
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 070b3339e0d059d77077b85b86048cf6479a1720a0c6266d89f55a1723e119ec
User & Date: js on 2021-03-03 01:29:30
Other Links: manifest | tags
Context
2021-03-03
23:39
Add the various resource records check-in: e473ea9c63 user: js tags: trunk
01:29
Parse resolv.conf check-in: 070b3339e0 user: js tags: trunk
00:54
Initial import check-in: 5578a30548 user: js tags: trunk
Changes

Modified src/settings.cr from [09281d3bc1] to [9091c56abc].

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

Modified tests/example.cr from [c90f102b63] to [4658a8dbd9].

1
2
3
4
5
6
7







require "../src/asyncdns"

AsyncDNS::Query.new("crystal-lang.org", AsyncDNS::DNSClass::IN,
  AsyncDNS::RRType::A)

settings = AsyncDNS::Settings.new
p settings.static_hosts














>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
require "../src/asyncdns"

AsyncDNS::Query.new("crystal-lang.org", AsyncDNS::DNSClass::IN,
  AsyncDNS::RRType::A)

settings = AsyncDNS::Settings.new
p settings.static_hosts
p settings.nameservers
p settings.local_domain
p settings.search_domains
p settings.uses_tcp
p settings.timeout
p settings.max_attempts
p settings.abs_num_dots