unbound 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|