Skip to content

Commit 41c8166

Browse files
author
Brian Moran
committed
use a nonblocking socket, wait for socket in a select with a timeout
1 parent 51597ea commit 41c8166

File tree

1 file changed

+34
-8
lines changed

1 file changed

+34
-8
lines changed

lib/net/ldap.rb

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ def initialize(args = {})
383383
@verbose = false # Make this configurable with a switch on the class.
384384
@auth = args[:auth] || DefaultAuth
385385
@base = args[:base] || DefaultTreebase
386+
@timeout = args[:timeout] || 60
386387
encryption args[:encryption] # may be nil
387388

388389
if pr = @auth[:password] and pr.respond_to?(:call)
@@ -562,7 +563,7 @@ def open
562563
@open_connection = Net::LDAP::Connection.new(:host => @host,
563564
:port => @port,
564565
:encryption =>
565-
@encryption)
566+
@encryption, :timeout => @timeout)
566567
@open_connection.bind(@auth)
567568
yield self
568569
ensure
@@ -634,7 +635,7 @@ def search(args = {})
634635
else
635636
begin
636637
conn = Net::LDAP::Connection.new(:host => @host, :port => @port,
637-
:encryption => @encryption)
638+
:encryption => @encryption, :timeout => @timeout)
638639
if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
639640
@result = conn.search(args) { |entry|
640641
result_set << entry if result_set
@@ -716,7 +717,7 @@ def bind(auth = @auth)
716717
else
717718
begin
718719
conn = Connection.new(:host => @host, :port => @port,
719-
:encryption => @encryption)
720+
:encryption => @encryption, :timeout => @timeout)
720721
@result = conn.bind(auth)
721722
ensure
722723
conn.close if conn
@@ -817,7 +818,7 @@ def add(args)
817818
@result = 0
818819
begin
819820
conn = Connection.new(:host => @host, :port => @port,
820-
:encryption => @encryption)
821+
:encryption => @encryption, :timeout => @timeout)
821822
if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
822823
@result = conn.add(args)
823824
end
@@ -915,7 +916,7 @@ def modify(args)
915916
@result = 0
916917
begin
917918
conn = Connection.new(:host => @host, :port => @port,
918-
:encryption => @encryption)
919+
:encryption => @encryption, :timeout => @timeout)
919920
if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
920921
@result = conn.modify(args)
921922
end
@@ -987,7 +988,7 @@ def rename(args)
987988
@result = 0
988989
begin
989990
conn = Connection.new(:host => @host, :port => @port,
990-
:encryption => @encryption)
991+
:encryption => @encryption, :timeout => @timeout)
991992
if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
992993
@result = conn.rename(args)
993994
end
@@ -1015,7 +1016,7 @@ def delete(args)
10151016
@result = 0
10161017
begin
10171018
conn = Connection.new(:host => @host, :port => @port,
1018-
:encryption => @encryption)
1019+
:encryption => @encryption, :timeout => @timeout)
10191020
if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
10201021
@result = conn.delete(args)
10211022
end
@@ -1119,9 +1120,34 @@ class Net::LDAP::Connection #:nodoc:
11191120
LdapVersion = 3
11201121
MaxSaslChallenges = 10
11211122

1123+
def socket_connect_with_timeout(host, port, timeout=nil)
1124+
addr = Socket.getaddrinfo(host, nil)
1125+
sock = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)
1126+
1127+
if timeout
1128+
secs = Integer(timeout)
1129+
usecs = Integer((timeout - secs) * 1_000_000)
1130+
optval = [secs, usecs].pack("l_2")
1131+
1132+
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval
1133+
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
1134+
end
1135+
1136+
begin
1137+
sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3]))
1138+
rescue Errno::EINPROGRESS => ex
1139+
rzult = select([sock], [sock], [sock], timeout)
1140+
if !rzult
1141+
raise Errno::ETIMEDOUT, "Timeout #{timeout ? "(#{timeout} seconds)" : "(default)"} exceeded"
1142+
end
1143+
end
1144+
return sock
1145+
end
1146+
11221147
def initialize(server)
11231148
begin
1124-
@conn = TCPSocket.new(server[:host], server[:port])
1149+
@conn = socket_connect_with_timeout(server[:host], server[:port], server[:timeout])
1150+
#@conn = TCPSocket.new(server[:host], server[:port])
11251151
rescue SocketError
11261152
raise Net::LDAP::LdapError, "No such address or other socket error."
11271153
rescue Errno::ECONNREFUSED

0 commit comments

Comments
 (0)