AsyncDNS-cr  Check-in [c210ddc089]

Overview
Comment:Some cleanups
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: c210ddc089b9b0140f9aa6257c2536755e624bf76b41856ae4cc1ccbd536c53b
User & Date: js on 2021-03-04 02:09:32
Other Links: manifest | tags
Context
2021-03-05
00:59
Initial support for sending the query check-in: b6cfd2fe24 user: js tags: trunk
2021-03-04
02:09
Some cleanups check-in: c210ddc089 user: js tags: trunk
01:03
Initial work on sending a query check-in: baf27b579c user: js tags: trunk
Changes

Modified src/query.cr from [f77640a093] to [67a7ba4afc].

1
2
3
4
5
6


7
8
9
10
11
require "./dns_class"
require "./rr_type"

module AsyncDNS
  class Query
    getter :name, :class, :type



    def initialize(@name : String, @class : DNSClass, @type : RRType)
    end
  end
end





|
>
>





1
2
3
4
5
6
7
8
9
10
11
12
13
require "./dns_class"
require "./rr_type"

module AsyncDNS
  class Query
    getter name : String
    getter class : DNSClass
    getter type : RRType

    def initialize(@name : String, @class : DNSClass, @type : RRType)
    end
  end
end

Modified src/resolver.cr from [e08367333f] to [389b0620fd].

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
require "./rr"
require "./settings"
require "./response"

module AsyncDNS
  class Resolver
    getter :settings

    enum Error
      NO_NAME_SERVER
    end

    private struct Context
      def initialize(@id : UInt16, @settings : Settings,
                     @block : Response | Error ->)
      end
    end

    def initialize
      @settings = Settings.new
      @queries = Hash(UInt16, Context).new
      @tcp_queries = Hash(Socket, Context).new
    end

    def resolve(query, &block : Response | Error ->)
      id : UInt16
      while true
        id = Random::Secure.rand(UInt16::MIN..UInt16::MAX)
        break unless @queries.has_key?(id)
      end

      if @settings.nameservers.empty?
        yield Error::NO_NAME_SERVER
        return
      end

      send(Context.new(id, settings.dup, block))
    end

    def send(context : Context)
      @queries[context.@id] = context

      # TODO
    end

    def stop
      # TODO
    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
require "./rr"
require "./settings"
require "./response"

module AsyncDNS
  class Resolver
    getter settings : Settings

    enum Error
      NO_NAME_SERVER
    end


    private record Context, id : UInt16, settings : Settings,
      block : Response | Error ->



    def initialize
      @settings = Settings.new
      @queries = Hash(UInt16, Context).new
      @tcp_queries = Hash(Socket, Context).new
    end

    def resolve(query : Query, &block : Response | Error ->)
      id : UInt16
      while true
        id = Random::Secure.rand(UInt16::MIN..UInt16::MAX)
        break unless @queries.has_key?(id)
      end

      if @settings.nameservers.empty?
        yield Error::NO_NAME_SERVER
        return
      end

      send(Context.new(id, settings.dup, block))
    end

    private def send(context : Context)
      @queries[context.@id] = context

      # TODO
    end

    def stop
      # TODO
    end
  end
end

Modified src/response.cr from [96a20ec37e] to [05324bedeb].

1
2
3
4
5



6
7
8
9
10
11
require "./rr"

module AsyncDNS
  class Response
    property :name, :answer, :authority, :additional




    def initialize(@name : String, @answer : Array(RR), @authority : Array(RR),
                   @additional : Array(RR))
    end
  end
end




|
>
>
>






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

module AsyncDNS
  class Response
    property name : String
    property answer : Array(RR)
    property authority : Array(RR)
    property additional : Array(RR)

    def initialize(@name : String, @answer : Array(RR), @authority : Array(RR),
                   @additional : Array(RR))
    end
  end
end

Modified src/rr.cr from [c7ffec3a5e] to [2fc5a6484f].

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
require "socket"

module AsyncDNS
  abstract struct RR
    property :name, :class, :type, :ttl




    def initialize(@name : String, @class : DNSClass, @type : RRType,
                   @ttl : Int32)
    end

    struct A < RR
      property :address

      def initialize(name, @address : Socket::IPAddress, ttl)
        super(name, DNSClass::IN, RRType::A, ttl)
      end
    end

    struct AAAA < RR
      property :address

      def initialize(name, @address : Socket::IPAddress, ttl)
        super(name, DNSClass::IN, RRType::AAAA, ttl)
      end
    end

    struct CNAME < RR
      property :alias

      def initialize(name, @alias : String, ttl)
        super(name, DNSClass::IN, RRType::CNAME, ttl)
      end
    end

    struct HINFO < RR
      property :cpu, :os


      def initialize(name, @cpu : String, @os : String, ttl)
        super(name, DNSClass::IN, RRType::HINFO, ttl)
      end
    end

    struct MX < RR

      property :preference, :mx

      def initialize(name, @preference : UInt16, @mx : String, ttl)

        super(name, DNSClass::IN, RRType::MX, ttl)
      end
    end

    struct NS < RR
      property :authority

      def initialize(name, @authority : String, ttl)
        super(name, DNSClass::IN, RRType::NS, ttl)
      end
    end

    struct PTR < RR
      property :domain

      def initialize(name, @domain : String, ttl)
        super(name, DNSClass::IN, RRType::PTR, ttl)
      end
    end

    struct RP < RR
      property :mailbox, :domain


      def initialize(name, @mailbox : String, @domain : String, ttl)

        super(name, DNSClass::IN, RRType::RP, ttl)
      end
    end

    struct SOA < RR




      property :primary_ns, :responsible, :serial, :refresh, :retry,

        :expire, :min_ttl

      def initialize(name, @primary_ns : String, @responsible : String,
                     @serial : UInt32, @refresh : UInt32, @retry : UInt32,
                     @expire : UInt32, @min_ttl : UInt32)
        super(name, DNSClass::IN, RRType::SOA, ttl)
      end
    end

    struct SRV < RR
      property :prio, :weight, :target, :port




      def initialize(name, @prio : UInt16, @weight : UInt16, @target : String,
                     @port : UInt16, ttl)
        super(name, DNSClass::IN, RRType::SRV, ttl)
      end
    end

    struct TXT < RR
      property :text

      def initialize(name, @text : Array(String), ttl)
        super(name, DNSClass::IN, RRType::TXT)
      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
require "socket"

module AsyncDNS
  abstract struct RR
    property name : String
    property class : DNSClass
    property type : RRType
    property ttl : UInt32

    def initialize(@name : String, @class : DNSClass, @type : RRType,
                   @ttl : UInt32)
    end

    struct A < RR
      property address : Socket::IPAddress

      def initialize(name : String, @address : Socket::IPAddress, ttl : UInt32)
        super(name, :in, :a, ttl)
      end
    end

    struct AAAA < RR
      property address : Socket::IPAddress

      def initialize(name : String, @address : Socket::IPAddress, ttl : UInt32)
        super(name, :in, :aaaa, ttl)
      end
    end

    struct CNAME < RR
      property alias : String

      def initialize(name : String, @alias : String, ttl : UInt32)
        super(name, :in, :cname, ttl)
      end
    end

    struct HINFO < RR
      property cpu : String
      property os : String

      def initialize(name : String, @cpu : String, @os : String, ttl : UInt32)
        super(name, :in, :hinfo, ttl)
      end
    end

    struct MX < RR
      property preference : UInt16
      property mx : String

      def initialize(name : String, @preference : UInt16, @mx : String,
                     ttl : UInt32)
        super(name, :in, :mx, ttl)
      end
    end

    struct NS < RR
      property authority : String

      def initialize(name : String, @authority : String, ttl : UInt32)
        super(name, :in, :ns, ttl)
      end
    end

    struct PTR < RR
      property domain : String

      def initialize(name : String, @domain : String, ttl : UInt32)
        super(name, :in, :ptr, ttl)
      end
    end

    struct RP < RR
      property mailbox : String
      property domain : String

      def initialize(name : String, @mailbox : String, @domain : String,
                     ttl : UInt32)
        super(name, :in, :rp, ttl)
      end
    end

    struct SOA < RR
      property primary_ns : String
      property responsible : String
      property serial : UInt32
      property refresh : UInt32
      property retry : UInt32
      property expire : UInt32
      property min_ttl : UInt32

      def initialize(name : String, @primary_ns : String, @responsible : String,
                     @serial : UInt32, @refresh : UInt32, @retry : UInt32,
                     @expire : UInt32, @min_ttl : UInt32, ttl : UInt32)
        super(name, :in, :soa, ttl)
      end
    end

    struct SRV < RR
      property prio : UInt16
      property weight : UInt16
      property target : String
      property port : UInt16

      def initialize(name : String, @prio : UInt16, @weight : UInt16,
                     @target : String, @port : UInt16, ttl : UInt32)
        super(name, :in, :srv, ttl)
      end
    end

    struct TXT < RR
      property text : Array(String)

      def initialize(name : String, @text : Array(String), ttl : UInt32)
        super(name, :in, :txt)
      end
    end
  end
end

Modified src/settings.cr from [a3be16cbc5] to [5585feb972].

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
module AsyncDNS
  class Settings
    @local_domain : String?




    property :static_hosts, :nameservers, :local_domain, :search_domains,

      :uses_tcp, :reload_period

    getter :timeout, :max_attempts, :abs_num_dots


    def timeout=(timeout)
      if timeout < Time::Span.zero
        raise ArgumentError.new("timeout must be positive")
      end

      @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





>
>
>
|
>
|
>
|
>

|







|







|







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
module AsyncDNS
  class Settings
    @local_domain : String?

    property static_hosts : Hash(String, Array(String))
    property nameservers : Array(String)
    property local_domain : String?
    property search_domains : Array(String)
    property uses_tcp : Bool
    property reload_period : Time::Span
    getter timeout : Time::Span
    getter max_attempts : Int32
    getter abs_num_dots : Int32

    def timeout=(timeout : Time::Span)
      if timeout < Time::Span.zero
        raise ArgumentError.new("timeout must be positive")
      end

      @timeout = timeout
    end

    def max_attempts=(max_attempts : Int32)
      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 : Int32)
      if abs_num_dots < 0
        raise ArgumentError.new("abs_num_dots must be positive")
      end

      @abs_num_dots = abs_num_dots
    end

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
      {% else %}
        {% raise "Your OS is not supported by AsyncDNS" %}
      {% end %}

      @last_reload = Time.monotonic
    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)







|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
      {% else %}
        {% raise "Your OS is not supported by AsyncDNS" %}
      {% end %}

      @last_reload = Time.monotonic
    end

    private 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)
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
          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







|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
          end

          addresses << address
        end
      end
    end

    private 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