Skip to content

Commit 4b22ea7

Browse files
committed
Merge pull request #224 from javanthropus/dry_up_connection_handling
DRY up connection handling logic
2 parents 4667a08 + e829069 commit 4b22ea7

File tree

3 files changed

+50
-43
lines changed

3 files changed

+50
-43
lines changed

lib/net/ldap/connection.rb

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,43 @@ class Net::LDAP::Connection #:nodoc:
88

99
def initialize(server)
1010
@instrumentation_service = server[:instrumentation_service]
11-
server[:hosts] = [[server[:host], server[:port]]] if server[:hosts].nil?
1211

1312
if server[:socket]
1413
prepare_socket(server)
1514
else
15+
server[:hosts] = [[server[:host], server[:port]]] if server[:hosts].nil?
1616
open_connection(server)
1717
end
1818

1919
yield self if block_given?
2020
end
2121

2222
def prepare_socket(server)
23-
@conn = server[:socket]
23+
socket = server[:socket]
24+
encryption = server[:encryption]
2425

25-
if server[:encryption]
26-
setup_encryption server[:encryption]
27-
end
26+
@conn = socket
27+
setup_encryption encryption if encryption
2828
end
2929

3030
def open_connection(server)
31+
hosts = server[:hosts]
32+
encryption = server[:encryption]
33+
3134
errors = []
32-
server[:hosts].each do |host, port|
35+
hosts.each do |host, port|
3336
begin
34-
return connect_to_host(host, port, server)
35-
rescue Net::LDAP::Error
36-
errors << $!
37+
prepare_socket(server.merge(socket: TCPSocket.new(host, port)))
38+
return
39+
rescue Net::LDAP::Error, SocketError, SystemCallError,
40+
OpenSSL::SSL::SSLError => e
41+
# Ensure the connection is closed in the event a setup failure.
42+
close
43+
errors << [e, host, port]
3744
end
3845
end
3946

40-
raise errors.first if errors.size == 1
41-
raise Net::LDAP::Error,
42-
"Unable to connect to any given server: \n #{errors.join("\n ")}"
43-
end
44-
45-
def connect_to_host(host, port, server)
46-
begin
47-
@conn = TCPSocket.new(host, port)
48-
rescue SocketError
49-
raise Net::LDAP::Error, "No such address or other socket error."
50-
rescue Errno::ECONNREFUSED
51-
raise Net::LDAP::ConnectionRefusedError, "Server #{host} refused connection on port #{port}."
52-
rescue Errno::EHOSTUNREACH => error
53-
raise Net::LDAP::Error, "Host #{host} was unreachable (#{error.message})"
54-
rescue Errno::ETIMEDOUT
55-
raise Net::LDAP::Error, "Connection to #{host} timed out."
56-
end
57-
58-
if server[:encryption]
59-
setup_encryption server[:encryption]
60-
end
47+
raise Net::LDAP::ConnectionError.new(errors)
6148
end
6249

6350
module GetbyteForSSLSocket
@@ -156,6 +143,7 @@ def setup_encryption(args)
156143
# have to call it, but perhaps it will come in handy someday.
157144
#++
158145
def close
146+
return if @conn.nil?
159147
@conn.close
160148
@conn = nil
161149
end

lib/net/ldap/error.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,25 @@ def warn_deprecation_message
2525
warn "Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead."
2626
end
2727
end
28+
class ConnectionError < Error
29+
def self.new(errors)
30+
error = errors.first.first
31+
if errors.size == 1
32+
if error.kind_of? Errno::ECONNREFUSED
33+
return Net::LDAP::ConnectionRefusedError.new(error.message)
34+
end
35+
36+
return Net::LDAP::Error.new(error.message)
37+
end
38+
39+
super
40+
end
41+
42+
def initialize(errors)
43+
message = "Unable to connect to any given server: \n #{errors.map { |e, h, p| "#{e.class}: #{e.message} (#{h}:#{p})" }.join("\n ")}"
44+
super(message)
45+
end
46+
end
2847
class NoOpenSSLError < Error; end
2948
class NoStartTLSResultError < Error; end
3049
class NoSearchBaseError < Error; end

test/test_ldap_connection.rb

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ def capture_stderr
1111

1212
def test_list_of_hosts_with_first_host_successful
1313
hosts = [
14-
['test.mocked.com', 636],
15-
['test2.mocked.com', 636],
16-
['test3.mocked.com', 636],
17-
]
14+
['test.mocked.com', 636],
15+
['test2.mocked.com', 636],
16+
['test3.mocked.com', 636],
17+
]
1818
flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_return(nil)
1919
flexmock(TCPSocket).should_receive(:new).ordered.never
2020
Net::LDAP::Connection.new(:hosts => hosts)
2121
end
2222

2323
def test_list_of_hosts_with_first_host_failure
2424
hosts = [
25-
['test.mocked.com', 636],
26-
['test2.mocked.com', 636],
27-
['test3.mocked.com', 636],
28-
]
25+
['test.mocked.com', 636],
26+
['test2.mocked.com', 636],
27+
['test3.mocked.com', 636],
28+
]
2929
flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError)
3030
flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_return(nil)
3131
flexmock(TCPSocket).should_receive(:new).ordered.never
@@ -34,15 +34,15 @@ def test_list_of_hosts_with_first_host_failure
3434

3535
def test_list_of_hosts_with_all_hosts_failure
3636
hosts = [
37-
['test.mocked.com', 636],
38-
['test2.mocked.com', 636],
39-
['test3.mocked.com', 636],
40-
]
37+
['test.mocked.com', 636],
38+
['test2.mocked.com', 636],
39+
['test3.mocked.com', 636],
40+
]
4141
flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError)
4242
flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_raise(SocketError)
4343
flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[2]).once.and_raise(SocketError)
4444
flexmock(TCPSocket).should_receive(:new).ordered.never
45-
assert_raise Net::LDAP::Error do
45+
assert_raise Net::LDAP::ConnectionError do
4646
Net::LDAP::Connection.new(:hosts => hosts)
4747
end
4848
end

0 commit comments

Comments
 (0)