Skip to content
This repository has been archived by the owner on Jan 2, 2023. It is now read-only.

Commit

Permalink
Use Resolv.getaddresses instead of Socket.getaddrinfo
Browse files Browse the repository at this point in the history
This is an experiment to see if I can get to the bottom of #50
  • Loading branch information
iconara committed Oct 28, 2013
1 parent 968d6eb commit 27337b8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 17 deletions.
26 changes: 19 additions & 7 deletions lib/cql/io/connection.rb
@@ -1,6 +1,7 @@
# encoding: utf-8

require 'socket'
require 'resolv'


module Cql
Expand All @@ -13,13 +14,14 @@ class Connection
attr_reader :host, :port, :connection_timeout

# @private
def initialize(host, port, connection_timeout, unblocker, clock, socket_impl=Socket)
def initialize(host, port, connection_timeout, unblocker, clock, socket_impl=Socket, resolv_impl=Resolv)
@host = host
@port = port
@connection_timeout = connection_timeout
@unblocker = unblocker
@clock = clock
@socket_impl = socket_impl
@resolv_impl = resolv_impl
@lock = Mutex.new
@connected = false
@write_buffer = ByteBuffer.new
Expand All @@ -29,14 +31,24 @@ def initialize(host, port, connection_timeout, unblocker, clock, socket_impl=Soc
# @private
def connect
begin
unless @addrinfos
unless @addresses
@connection_started_at = @clock.now
@addrinfos = @socket_impl.getaddrinfo(@host, @port, nil, Socket::SOCK_STREAM)
@addresses = @resolv_impl.getaddresses(@host)
end
unless @io
_, port, _, ip, address_family, socket_type = @addrinfos.shift
@sockaddr = @socket_impl.sockaddr_in(port, ip)
@io = @socket_impl.new(address_family, socket_type, 0)
address = nil
begin
address_str = @addresses.shift
address = IPAddr.new(address_str)
rescue ArgumentError => e
if @addresses.empty?
close(ConnectionError.new(%(Could not resolve hostname "#{@host}")))
else
retry
end
end
@sockaddr = @socket_impl.sockaddr_in(@port, address.to_s)
@io = @socket_impl.new(address.family, Socket::SOCK_STREAM)
end
unless connected?
@io.connect_nonblock(@sockaddr)
Expand All @@ -51,7 +63,7 @@ def connect
close(ConnectionTimeoutError.new("Could not connect to #{@host}:#{@port} within #{@connection_timeout}s"))
end
rescue Errno::EINVAL => e
if @addrinfos.empty?
if @addresses.empty?
close(e)
else
@io = nil
Expand Down
24 changes: 14 additions & 10 deletions spec/cql/io/connection_spec.rb
Expand Up @@ -7,7 +7,7 @@ module Cql
module Io
describe Connection do
let :handler do
described_class.new('example.com', 55555, 5, unblocker, clock, socket_impl)
described_class.new('example.com', 55555, 5, unblocker, clock, socket_impl, resolv_impl)
end

let :unblocker do
Expand All @@ -18,6 +18,10 @@ module Io
double(:socket_impl)
end

let :resolv_impl do
double(:resolv_impl)
end

let :clock do
double(:clock, now: 0)
end
Expand All @@ -27,14 +31,14 @@ module Io
end

before do
socket_impl.stub(:getaddrinfo)
.with('example.com', 55555, nil, Socket::SOCK_STREAM)
.and_return([[nil, 'PORT', nil, 'IP1', 'FAMILY1', 'TYPE1'], [nil, 'PORT', nil, 'IP2', 'FAMILY2', 'TYPE2']])
resolv_impl.stub(:getaddresses)
.with('example.com')
.and_return(['1.1.1.1', '2.2.2.2'])
socket_impl.stub(:sockaddr_in)
.with('PORT', 'IP1')
.with(55555, '1.1.1.1')
.and_return('SOCKADDR1')
socket_impl.stub(:new)
.with('FAMILY1', 'TYPE1', 0)
.with(Socket::AF_INET, Socket::SOCK_STREAM)
.and_return(socket)
end

Expand Down Expand Up @@ -116,10 +120,10 @@ module Io
context 'when #connect_nonblock raises EINVAL' do
before do
socket_impl.stub(:sockaddr_in)
.with('PORT', 'IP2')
.with(55555, '2.2.2.2')
.and_return('SOCKADDR2')
socket_impl.stub(:new)
.with('FAMILY2', 'TYPE2', 0)
.with(Socket::AF_INET, Socket::SOCK_STREAM)
.and_return(socket)
socket.stub(:close)
end
Expand Down Expand Up @@ -173,9 +177,9 @@ module Io
end
end

context 'when Socket.getaddrinfo raises SocketError' do
context 'when Resolv.getaddresses raises SocketError' do
before do
socket_impl.stub(:getaddrinfo).and_raise(SocketError)
resolv_impl.stub(:getaddresses).and_raise(SocketError)
end

it 'fails the returned future with a ConnectionError' do
Expand Down

0 comments on commit 27337b8

Please sign in to comment.