Skip to content

Commit cf557ce

Browse files
committed
Merge pull request #602 from estolfo/FREE-72862-resolvers
FREE-72862 Refactor resolvers and address to try different protocol families
2 parents 6858590 + a5b61db commit cf557ce

File tree

7 files changed

+64
-71
lines changed

7 files changed

+64
-71
lines changed

lib/mongo/address.rb

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,22 @@ module Mongo
2525
class Address
2626
extend Forwardable
2727

28-
# Delegate the ip, host, and port methods to the resolver.
28+
# Mapping from socket family to resolver class.
2929
#
3030
# @since 2.0.0
31-
def_delegators :@resolver, :host, :port, :socket, :seed, :to_s
31+
FAMILY_MAP = { ::Socket::PF_UNIX => Unix,
32+
::Socket::AF_INET6 => IPv6,
33+
::Socket::AF_INET => IPv4
34+
}
3235

33-
# @return [ Integer ] port The port to the connect to.
34-
attr_reader :resolver
36+
# @return [ String ] address The seed address.
37+
attr_reader :seed
38+
39+
# @return [ String ] host The original host name.
40+
attr_reader :host
41+
42+
# @return [ Integer ] port The port.
43+
attr_reader :port
3544

3645
# Check equality of the address to another.
3746
#
@@ -88,13 +97,8 @@ def hash
8897
#
8998
# @since 2.0.0
9099
def initialize(seed, options = {})
91-
address = seed.downcase
92-
host, port = match(address)
93-
case family(host)
94-
when ::Socket::PF_UNIX then @resolver = Unix.new(host, address)
95-
when ::Socket::AF_INET6 then @resolver = IPv6.new(host, port, address)
96-
else @resolver = IPv4.new(host, port, address)
97-
end
100+
@seed = seed
101+
@host, @port = parse_host_port
98102
end
99103

100104
# Get a pretty printed address inspection.
@@ -106,17 +110,55 @@ def initialize(seed, options = {})
106110
#
107111
# @since 2.0.0
108112
def inspect
109-
"#<Mongo::Address:0x#{object_id} address=#{resolver.to_s}>"
113+
"#<Mongo::Address:0x#{object_id} address=#{to_s}>"
114+
end
115+
116+
# Get a socket for the provided address, given the options.
117+
#
118+
# @example Get a socket.
119+
# address.socket(5, :ssl => true)
120+
#
121+
# @param [ Float ] timeout The socket timeout.
122+
# @param [ Hash ] ssl_options SSL options.
123+
#
124+
# @return [ Pool::Socket::SSL, Pool::Socket::TCP, Pool::Socket::Unix ] The socket.
125+
#
126+
# @since 2.0.0
127+
def socket(timeout, ssl_options = {})
128+
@resolver ||= initialize_resolver!(timeout, ssl_options)
129+
@resolver.socket(timeout, ssl_options)
130+
end
131+
132+
# Get the address as a string.
133+
#
134+
# @example Get the address as a string.
135+
# address.to_s
136+
#
137+
# @return [ String ] The nice string.
138+
#
139+
# @since 2.0.0
140+
def to_s
141+
port ? "#{host}:#{port}" : host
110142
end
111143

112144
private
113145

114-
def family(host)
115-
fam = (host == 'localhost') ? ::Socket::AF_INET : ::Socket::AF_UNSPEC
116-
::Socket.getaddrinfo(host, nil, fam, ::Socket::SOCK_STREAM).first[4]
146+
def initialize_resolver!(timeout, ssl_options)
147+
family = (host == 'localhost') ? ::Socket::AF_INET : ::Socket::AF_UNSPEC
148+
::Socket.getaddrinfo(host, nil, family, ::Socket::SOCK_STREAM).detect do |info|
149+
begin
150+
return FAMILY_MAP[info[4]].new(host, port).tap do |res|
151+
res.socket(timeout, ssl_options).connect!
152+
end
153+
rescue IOError, SystemCallError => e
154+
error = e
155+
end
156+
end
157+
raise error
117158
end
118159

119-
def match(address)
160+
def parse_host_port
161+
address = seed.downcase
120162
case address
121163
when Unix::MATCH then Unix.parse(address)
122164
when IPv6::MATCH then IPv6.parse(address)

lib/mongo/address/ipv4.rb

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ class IPv4
2727
# @return [ Integer ] port The port.
2828
attr_reader :port
2929

30-
# @return [ String ] seed The seed address.
31-
attr_reader :seed
32-
3330
# The regular expression to use to match an IPv4 ip address.
3431
#
3532
# @since 2.0.0
@@ -59,13 +56,11 @@ def self.parse(address)
5956
#
6057
# @param [ String ] host The host.
6158
# @param [ Integer ] port The port.
62-
# @param [ String ] address The seed address.
6359
#
6460
# @since 2.0.0
65-
def initialize(host, port, address)
61+
def initialize(host, port)
6662
@host = host
6763
@port = port
68-
@seed = address
6964
end
7065

7166
# Get a socket for the provided address type, given the options.
@@ -86,18 +81,6 @@ def socket(timeout, ssl_options = {})
8681
Socket::TCP.new(host, port, timeout, Socket::PF_INET)
8782
end
8883
end
89-
90-
# Get the address as a string.
91-
#
92-
# @example Get the address as a string.
93-
# ipv4.to_s
94-
#
95-
# @return [ String ] The nice string.
96-
#
97-
# @since 2.0.0
98-
def to_s
99-
"#{host}:#{port}"
100-
end
10184
end
10285
end
10386
end

lib/mongo/address/ipv6.rb

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ class IPv6
2727
# @return [ Integer ] port The port.
2828
attr_reader :port
2929

30-
# @return [ String ] seed The seed address.
31-
attr_reader :seed
32-
3330
# The regular expression to use to match an IPv6 ip address.
3431
#
3532
# @since 2.0.0
@@ -59,13 +56,11 @@ def self.parse(address)
5956
#
6057
# @param [ String ] host The host.
6158
# @param [ Integer ] port The port.
62-
# @param [ String ] address The seed address.
6359
#
6460
# @since 2.0.0
65-
def initialize(host, port, address)
61+
def initialize(host, port)
6662
@host = host
6763
@port = port
68-
@seed = address
6964
end
7065

7166
# Get a socket for the provided address type, given the options.
@@ -86,18 +81,6 @@ def socket(timeout, ssl_options = {})
8681
Socket::TCP.new(host, port, timeout, Socket::PF_INET6)
8782
end
8883
end
89-
90-
# Get the address as a string.
91-
#
92-
# @example Get the address as a string.
93-
# ipv4.to_s
94-
#
95-
# @return [ String ] The nice string.
96-
#
97-
# @since 2.0.0
98-
def to_s
99-
"#{host}:#{port}"
100-
end
10184
end
10285
end
10386
end

lib/mongo/address/unix.rb

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ class Unix
2626
# @return [ nil ] port Will always be nil.
2727
attr_reader :port
2828

29-
# @return [ String ] seed The seed address.
30-
attr_reader :seed
31-
3229
# The regular expression to use to match a socket path.
3330
#
3431
# @since 2.0.0
@@ -54,12 +51,10 @@ def self.parse(address)
5451
# Unix.new("/path/to/socket.sock", "/path/to/socket.sock")
5552
#
5653
# @param [ String ] host The host.
57-
# @param [ String ] address The seed address.
5854
#
5955
# @since 2.0.0
60-
def initialize(host, address)
56+
def initialize(host)
6157
@host = host
62-
@seed = address
6358
end
6459

6560
# Get a socket for the provided address type, given the options.
@@ -76,16 +71,6 @@ def initialize(host, address)
7671
def socket(timeout, ssl_options = {})
7772
Socket::Unix.new(host, timeout, Socket::AF_UNIX)
7873
end
79-
80-
# Get the address as a string.
81-
#
82-
# @example Get the address as a string.
83-
# ipv4.to_s
84-
#
85-
# @return [ String ] The nice string.
86-
#
87-
# @since 2.0.0
88-
alias :to_s :host
8974
end
9075
end
9176
end

spec/mongo/address/ipv4_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
describe Mongo::Address::IPv4 do
44

55
let(:resolver) do
6-
described_class.new(*described_class.parse(address), address)
6+
described_class.new(*described_class.parse(address))
77
end
88

99
describe 'self.parse' do

spec/mongo/address/ipv6_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
end
99

1010
let(:resolver) do
11-
described_class.new(*described_class.parse(address), address)
11+
described_class.new(*described_class.parse(address))
1212
end
1313

1414
describe 'self.parse' do

spec/mongo/address/unix_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
end
99

1010
let(:resolver) do
11-
described_class.new(*described_class.parse(address), address)
11+
described_class.new(*described_class.parse(address))
1212
end
1313

1414
describe 'self.parse' do

0 commit comments

Comments
 (0)