unbound 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Rakefile +28 -21
- data/VERSION +1 -1
- data/lib/unbound/query_store.rb +54 -0
- data/lib/unbound/resolver.rb +7 -9
- data/spec/query_store_spec.rb +139 -0
- metadata +4 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 268e920fce264b5a8fb5a60fc0f3b98d2648adde
|
4
|
+
data.tar.gz: fabfee310e6715df1e05e7ba455ae9fc64ae8f47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 634924d61b650aeba4ee82632b34d95040da7aec61ac8a0a632fc3c4b48aeb082c0aca829b0baac77d5647880b933bf711f24f87b88eecc740489f3361dec432
|
7
|
+
data.tar.gz: 8029d61671926ea5874d9c2c4060cf788e11eae74e8c4d60228b9613263ee4ede4b39b20f04767a2565cea8141eb5291cf1289c55aaebeca75501dd02709560a
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -9,28 +9,35 @@ rescue Bundler::BundlerError => e
|
|
9
9
|
end
|
10
10
|
require 'rake'
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
12
|
+
begin
|
13
|
+
require 'jeweler'
|
14
|
+
rescue LoadError
|
15
|
+
else
|
16
|
+
Jeweler::Tasks.new do |gem|
|
17
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
18
|
+
gem.name = "unbound"
|
19
|
+
gem.homepage = "http://github.com/justfalter/unbound-ruby"
|
20
|
+
gem.license = "MIT"
|
21
|
+
gem.summary = %Q{Unbound DNS resolver bindings for Ruby}
|
22
|
+
gem.description = %Q{Unbound DNS resolver bindings for Ruby}
|
23
|
+
gem.email = "falter@gmail.com"
|
24
|
+
gem.authors = ["Mike Ryan"]
|
25
|
+
gem.files = Dir.glob("lib/**/*.rb") +
|
26
|
+
Dir.glob("examples/*") +
|
27
|
+
Dir.glob("spec/{*.rb}") +
|
28
|
+
Dir.glob("spec/conf/{*.conf}") +
|
29
|
+
%w(LICENSE.txt Gemfile README.md Rakefile VERSION)
|
27
30
|
|
31
|
+
end
|
32
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
33
|
end
|
29
|
-
Jeweler::RubygemsDotOrgTasks.new
|
30
34
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
begin
|
36
|
+
rescue LoadError
|
37
|
+
else
|
38
|
+
require 'rspec/core'
|
39
|
+
require 'rspec/core/rake_task'
|
40
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
41
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
42
|
+
end
|
35
43
|
end
|
36
|
-
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.1
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Unbound
|
4
|
+
# Tracks in-flight queries for Resolver
|
5
|
+
class QueryStore
|
6
|
+
def initialize
|
7
|
+
@pointer_to_query_map = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Enumerates through each query.
|
11
|
+
def each
|
12
|
+
@pointer_to_query_map.each_value do |query|
|
13
|
+
yield(query)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Clears all queries from the store. No special actions taken.
|
18
|
+
def clear
|
19
|
+
@pointer_to_query_map.clear
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Integer] the number of queries in the store.
|
23
|
+
def count
|
24
|
+
@pointer_to_query_map.count
|
25
|
+
end
|
26
|
+
|
27
|
+
# Retreives the query from the store via the provided pointer.
|
28
|
+
# @param [FFI::Pointer] pointer
|
29
|
+
# @return [Unbound::Query, nil] The associated query, otherwise nil.
|
30
|
+
def get_by_pointer(pointer)
|
31
|
+
return nil if pointer.nil?
|
32
|
+
@pointer_to_query_map[pointer.address]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Stores a query object, and returns a pointer suitable for passing through
|
36
|
+
# Unbound::Context#resolve_async.
|
37
|
+
# @param [Unbound::Query] query
|
38
|
+
# @return [FFI::Pointer] the pointer
|
39
|
+
def store(query)
|
40
|
+
oid_ptr = FFI::Pointer.new query.object_id
|
41
|
+
@pointer_to_query_map[oid_ptr.address] = query
|
42
|
+
oid_ptr
|
43
|
+
end
|
44
|
+
|
45
|
+
# Deletes a query object from the store, and frees any associated pointer
|
46
|
+
# (if nescessary).
|
47
|
+
# @param [Unbound::Query] query
|
48
|
+
# @return [Unbound::Query] the query, if it was found. Otherwise nil.
|
49
|
+
def delete_query(query)
|
50
|
+
@pointer_to_query_map.delete(FFI::Pointer.new(query.object_id).address)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
data/lib/unbound/resolver.rb
CHANGED
@@ -2,6 +2,7 @@ require 'unbound/bindings'
|
|
2
2
|
require 'unbound/result'
|
3
3
|
require 'unbound/context'
|
4
4
|
require 'unbound/callbacks_mixin'
|
5
|
+
require 'unbound/query_store'
|
5
6
|
|
6
7
|
module Unbound
|
7
8
|
# A simple asynchronous resolver
|
@@ -12,7 +13,7 @@ module Unbound
|
|
12
13
|
# resolver.
|
13
14
|
def initialize(ctx)
|
14
15
|
@ctx = ctx
|
15
|
-
@queries =
|
16
|
+
@queries = QueryStore.new
|
16
17
|
@resolve_callback_func = FFI::Function.new(
|
17
18
|
:void, [:pointer, :int, :pointer],
|
18
19
|
self.method(:resolve_callback))
|
@@ -25,7 +26,7 @@ module Unbound
|
|
25
26
|
end
|
26
27
|
end
|
27
28
|
on_finish do |query|
|
28
|
-
@queries.
|
29
|
+
@queries.delete_query(query)
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
@@ -41,9 +42,7 @@ module Unbound
|
|
41
42
|
end
|
42
43
|
|
43
44
|
def resolve_callback(oid_ptr, err, result_ptr)
|
44
|
-
|
45
|
-
oid = oid_ptr.address
|
46
|
-
query = @queries[oid]
|
45
|
+
query = @queries.get_by_pointer(oid_ptr)
|
47
46
|
return if query.nil?
|
48
47
|
|
49
48
|
if err == 0
|
@@ -63,7 +62,7 @@ module Unbound
|
|
63
62
|
|
64
63
|
# Cancel all outstanding queries.
|
65
64
|
def cancel_all
|
66
|
-
@queries.
|
65
|
+
@queries.each do |query|
|
67
66
|
query.cancel!
|
68
67
|
end
|
69
68
|
@queries.clear
|
@@ -95,20 +94,19 @@ module Unbound
|
|
95
94
|
if query.started?
|
96
95
|
raise QueryAlreadyStarted.new
|
97
96
|
end
|
98
|
-
@queries[query.object_id] = query
|
99
97
|
# Add all of our callbacks, if any have been registered.
|
100
98
|
query.on_start(*@callbacks_start) unless @callbacks_start.empty?
|
101
99
|
query.on_answer(*@callbacks_answer) unless @callbacks_answer.empty?
|
102
100
|
query.on_error(*@callbacks_error) unless @callbacks_error.empty?
|
103
101
|
query.on_cancel(*@callbacks_cancel)
|
104
102
|
query.on_finish(*@callbacks_finish)
|
105
|
-
|
103
|
+
ptr = @queries.store(query)
|
106
104
|
async_id = @ctx.resolve_async(
|
107
105
|
query.name,
|
108
106
|
query.rrtype,
|
109
107
|
query.rrclass,
|
110
108
|
@resolve_callback_func,
|
111
|
-
|
109
|
+
ptr)
|
112
110
|
query.start!(async_id)
|
113
111
|
end
|
114
112
|
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Unbound::QueryStore do
|
4
|
+
let(:query_store) {
|
5
|
+
Unbound::QueryStore.new
|
6
|
+
}
|
7
|
+
|
8
|
+
def new_query(num)
|
9
|
+
Unbound::Query.new("somedomain#{num}.com", 1, 1)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#each" do
|
13
|
+
it "should yield as many times as there are queries in the store" do
|
14
|
+
5.times do |i|
|
15
|
+
query_store.store(new_query(i))
|
16
|
+
end
|
17
|
+
expect {|b| query_store.each(&b)}.to yield_control.exactly(5).times
|
18
|
+
end
|
19
|
+
it "should yield the set of query objects we put into it" do
|
20
|
+
expected_queries = []
|
21
|
+
actual_queries = []
|
22
|
+
5.times do |i|
|
23
|
+
query = new_query(i)
|
24
|
+
expected_queries << query
|
25
|
+
query_store.store(query)
|
26
|
+
end
|
27
|
+
query_store.each do |query|
|
28
|
+
actual_queries << query
|
29
|
+
end
|
30
|
+
expect(actual_queries).to match_array(expected_queries)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
describe "#clear" do
|
34
|
+
it "should cause the count to drop to 0" do
|
35
|
+
expect(query_store.count).to eq(0)
|
36
|
+
5.times do |i|
|
37
|
+
query_store.store(new_query(i))
|
38
|
+
end
|
39
|
+
expect(query_store.count).to eq(5)
|
40
|
+
query_store.clear
|
41
|
+
expect(query_store.count).to eq(0)
|
42
|
+
end
|
43
|
+
it "should remove all queries from the store, making it so they cannot be retreived" do
|
44
|
+
queries = {}
|
45
|
+
5.times do |i|
|
46
|
+
query = new_query(i)
|
47
|
+
ptr = query_store.store(query)
|
48
|
+
queries[ptr] = query
|
49
|
+
end
|
50
|
+
|
51
|
+
queries.each_pair do |ptr, query|
|
52
|
+
expect(query_store.get_by_pointer(ptr)).to be(query)
|
53
|
+
end
|
54
|
+
|
55
|
+
query_store.clear
|
56
|
+
queries.each_pair do |ptr, query|
|
57
|
+
expect(query_store.get_by_pointer(ptr)).to be_nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
describe "#count" do
|
62
|
+
it "should be 0 if there's nothing in there" do
|
63
|
+
expect(query_store.count).to eq(0)
|
64
|
+
end
|
65
|
+
it "should be 5 if five distinct queries have been added" do
|
66
|
+
5.times do |i|
|
67
|
+
query_store.store(new_query(i))
|
68
|
+
end
|
69
|
+
expect(query_store.count).to eq(5)
|
70
|
+
end
|
71
|
+
it "should be 1 if the same query was added 5 times" do
|
72
|
+
query = new_query(1)
|
73
|
+
5.times do |i|
|
74
|
+
query_store.store(query)
|
75
|
+
end
|
76
|
+
expect(query_store.count).to eq(1)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
describe "#store" do
|
80
|
+
it "should return a pointer" do
|
81
|
+
expect(query_store.store(new_query(1))).to be_a(FFI::Pointer)
|
82
|
+
end
|
83
|
+
it "should increase the count" do
|
84
|
+
query = new_query(1)
|
85
|
+
expect(query_store.count).to eq(0)
|
86
|
+
query_store.store(query)
|
87
|
+
expect(query_store.count).to eq(1)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
describe "#get_by_pointer" do
|
91
|
+
it "should return the query associated with the provided pointer" do
|
92
|
+
query1 = new_query(1)
|
93
|
+
query2 = new_query(2)
|
94
|
+
query3 = new_query(3)
|
95
|
+
query4 = new_query(4)
|
96
|
+
query5 = new_query(5)
|
97
|
+
ptr1 = query_store.store(query1)
|
98
|
+
ptr2 = query_store.store(query2)
|
99
|
+
ptr3 = query_store.store(query3)
|
100
|
+
ptr4 = query_store.store(query4)
|
101
|
+
ptr5 = query_store.store(query5)
|
102
|
+
expect(query_store.get_by_pointer(ptr1)).to be(query1)
|
103
|
+
expect(query_store.get_by_pointer(ptr2)).to be(query2)
|
104
|
+
expect(query_store.get_by_pointer(ptr3)).to be(query3)
|
105
|
+
expect(query_store.get_by_pointer(ptr4)).to be(query4)
|
106
|
+
expect(query_store.get_by_pointer(ptr5)).to be(query5)
|
107
|
+
end
|
108
|
+
it "should return nil if the provided pointer is not associated with a query" do
|
109
|
+
expect(query_store.get_by_pointer(FFI::Pointer.new(1234))).to be_nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
describe "#delete_query" do
|
113
|
+
it "should make it so the query can no longer be retreived from the store" do
|
114
|
+
query1 = new_query(1)
|
115
|
+
query2 = new_query(2)
|
116
|
+
ptr1 = query_store.store(query1)
|
117
|
+
ptr2 = query_store.store(query2)
|
118
|
+
expect(query_store.get_by_pointer(ptr1)).to be(query1)
|
119
|
+
expect(query_store.get_by_pointer(ptr2)).to be(query2)
|
120
|
+
query_store.delete_query(query1)
|
121
|
+
expect(query_store.get_by_pointer(ptr1)).to be_nil
|
122
|
+
expect(query_store.get_by_pointer(ptr2)).to be(query2)
|
123
|
+
query_store.delete_query(query2)
|
124
|
+
expect(query_store.get_by_pointer(ptr1)).to be_nil
|
125
|
+
expect(query_store.get_by_pointer(ptr2)).to be_nil
|
126
|
+
end
|
127
|
+
it "should return the query that was deleted" do
|
128
|
+
query1 = new_query(1)
|
129
|
+
ptr1 = query_store.store(query1)
|
130
|
+
expect(query_store.delete_query(query1)).to be(query1)
|
131
|
+
end
|
132
|
+
it "should return nil if the query was not in the store" do
|
133
|
+
query1 = new_query(1)
|
134
|
+
expect(query_store.delete_query(query1)).to be_nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unbound
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Ryan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - '>='
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - '>='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
41
|
description: Unbound DNS resolver bindings for Ruby
|
56
42
|
email: falter@gmail.com
|
57
43
|
executables: []
|
@@ -73,6 +59,7 @@ files:
|
|
73
59
|
- lib/unbound/context.rb
|
74
60
|
- lib/unbound/exceptions.rb
|
75
61
|
- lib/unbound/query.rb
|
62
|
+
- lib/unbound/query_store.rb
|
76
63
|
- lib/unbound/resolver.rb
|
77
64
|
- lib/unbound/result.rb
|
78
65
|
- spec/callback_array_spec.rb
|
@@ -80,6 +67,7 @@ files:
|
|
80
67
|
- spec/conf/test_config.conf
|
81
68
|
- spec/context_spec.rb
|
82
69
|
- spec/query_spec.rb
|
70
|
+
- spec/query_store_spec.rb
|
83
71
|
- spec/resolver_spec.rb
|
84
72
|
- spec/result_spec.rb
|
85
73
|
- spec/spec_helper.rb
|