AsyncDNS-cr  Check-in [baf27b579c]

Overview
Comment:Initial work on sending a query
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: baf27b579c8966f28bca64f61689693b2c7cc23598aa32fd863621731cbbfd94
User & Date: js on 2021-03-04 01:03:18
Other Links: manifest | tags
Context
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
2021-03-03
23:39
Add the various resource records check-in: e473ea9c63 user: js tags: trunk
Changes

Modified src/asyncdns.cr from [af9da1ad85] to [6cde53a6be].

1
2
3
4

5
6
7
require "./query"
require "./resolver"

# AsyncDNS is an asynchronous DNS resolver.

module AsyncDNS
  VERSION = "0.1.0"
end




>



1
2
3
4
5
6
7
8
require "./query"
require "./resolver"

# AsyncDNS is an asynchronous DNS resolver.
# It is a port of ObjFW's <https://objfw.nil.im> OFDNSResolver & friends.
module AsyncDNS
  VERSION = "0.1.0"
end

Modified src/query.cr from [ca3771abae] to [f77640a093].

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

module AsyncDNS
  class Query
    getter :domain_name, :dns_class, :rr_type

    def initialize(@domain_name : String, @dns_class : DNSClass,
                   @rr_type : RRType)
    end
  end
end





|

<
|



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

Modified src/resolver.cr from [e7d4d87a8a] to [e08367333f].

1
2

3
4
5
6
7



8






9
10


11






12




13















require "./rr"
require "./settings"


module AsyncDNS
  class Resolver
    getter :settings
    setter :settings










    def initialize
      @settings = Settings.new


    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
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

Added src/response.cr version [96a20ec37e].























>
>
>
>
>
>
>
>
>
>
>
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

Modified src/settings.cr from [24fadd9f43] to [a3be16cbc5].

1
2
3
4
5

6
7
8

9

10
11
12
13
14
15
16
module AsyncDNS
  class Settings
    @local_domain : String?

    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")




|
>
|


>
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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")

Modified tests/example.cr from [b547c51298] to [ea161df6fd].

1
2



3
4
5
6
7
8
9
require "../src/asyncdns"




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

resolver = AsyncDNS::Resolver.new

AsyncDNS::RR::A.new("crystal-lang.org", Socket::IPAddress.new("127.0.0.1", 0),
  1234)


>
>
>
|



|
<
<
1
2
3
4
5
6
7
8
9
10


require "../src/asyncdns"

AsyncDNS::RR::A.new("crystal-lang.org", Socket::IPAddress.new("127.0.0.1", 0),
  1234)

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

resolver = AsyncDNS::Resolver.new
resolver.resolve(query) { |response| p response }