Skip to content

Commit

Permalink
Merge pull request #2745 from crystal-lang/feature/old_getaddrinfo
Browse files Browse the repository at this point in the history
Don't use libevent's getaddrinfo, use C's getaddrinfo
Ary Borenszweig authored Jun 14, 2016

Verified

This commit was signed with the committer’s verified signature. The key has expired.
2 parents 3259b71 + 398a354 commit a3a6eac
Showing 9 changed files with 48 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/http/client.cr
Original file line number Diff line number Diff line change
@@ -240,6 +240,8 @@ class HTTP::Client
self.connect_timeout = connect_timeout.total_seconds
end

# **This method has no effect right now**
#
# Set the number of seconds to wait when resolving a name, before raising an `IO::Timeout`.
#
# ```
@@ -255,6 +257,8 @@ class HTTP::Client
@dns_timeout = dns_timeout.to_f
end

# **This method has no effect right now**
#
# Set the number of seconds to wait when resolving a name with a `Time::Span`, before raising an `IO::Timeout`.
#
# ```
2 changes: 2 additions & 0 deletions src/lib_c/i686-linux-gnu/c/netdb.cr
Original file line number Diff line number Diff line change
@@ -15,4 +15,6 @@ lib LibC
end

fun gai_strerror(ecode : Int) : Char*
fun getaddrinfo(hostname : Char*, servname : Char*, hints : Addrinfo*, res : Addrinfo**) : Int
fun freeaddrinfo(ai : Addrinfo*)
end
2 changes: 2 additions & 0 deletions src/lib_c/i686-linux-musl/c/netdb.cr
Original file line number Diff line number Diff line change
@@ -15,4 +15,6 @@ lib LibC
end

fun gai_strerror(x0 : Int) : Char*
fun getaddrinfo(hostname : Char*, servname : Char*, hints : Addrinfo*, res : Addrinfo**) : Int
fun freeaddrinfo(ai : Addrinfo*)
end
2 changes: 2 additions & 0 deletions src/lib_c/x86_64-linux-gnu/c/netdb.cr
Original file line number Diff line number Diff line change
@@ -15,4 +15,6 @@ lib LibC
end

fun gai_strerror(ecode : Int) : Char*
fun getaddrinfo(hostname : Char*, servname : Char*, hints : Addrinfo*, res : Addrinfo**) : Int
fun freeaddrinfo(ai : Addrinfo*)
end
2 changes: 2 additions & 0 deletions src/lib_c/x86_64-linux-musl/c/netdb.cr
Original file line number Diff line number Diff line change
@@ -15,4 +15,6 @@ lib LibC
end

fun gai_strerror(x0 : Int) : Char*
fun getaddrinfo(hostname : Char*, servname : Char*, hints : Addrinfo*, res : Addrinfo**) : Int
fun freeaddrinfo(ai : Addrinfo*)
end
2 changes: 2 additions & 0 deletions src/lib_c/x86_64-macosx-darwin/c/netdb.cr
Original file line number Diff line number Diff line change
@@ -15,4 +15,6 @@ lib LibC
end

fun gai_strerror(x0 : Int) : Char*
fun getaddrinfo(hostname : Char*, servname : Char*, hints : Addrinfo*, res : Addrinfo**) : Int
fun freeaddrinfo(ai : Addrinfo*)
end
2 changes: 2 additions & 0 deletions src/lib_c/x86_64-portbld-freebsd/c/netdb.cr
Original file line number Diff line number Diff line change
@@ -15,4 +15,6 @@ lib LibC
end

fun gai_strerror(x0 : Int) : Char*
fun getaddrinfo(hostname : Char*, servname : Char*, hints : Addrinfo*, res : Addrinfo**) : Int
fun freeaddrinfo(ai : Addrinfo*)
end
33 changes: 31 additions & 2 deletions src/socket/ip_socket.cr
Original file line number Diff line number Diff line change
@@ -41,10 +41,39 @@ class IPSocket < Socket
# (to connect or bind, for example), and false otherwise. If it returns false and
# the LibC::Addrinfo has a next LibC::Addrinfo, it is yielded to the block, and so on.
private def getaddrinfo(host, port, family, socktype, protocol = LibC::IPPROTO_IP, timeout = nil)
IPSocket.getaddrinfo(host, port, family, socktype, protocol, timeout) { |ai| yield ai }
# Using getaddrinfo from libevent doesn't work well,
# see https://github.com/crystal-lang/crystal/issues/2660
#
# For now it's better to have this working well but maybe a bit slow than
# having it working fast but something working bad or not seeing some networks.
IPSocket.getaddrinfo_c_call(host, port, family, socktype, protocol, timeout) { |ai| yield ai }
end

def self.getaddrinfo(host, port, family, socktype, protocol = LibC::IPPROTO_IP, timeout = nil)
# :nodoc:
def self.getaddrinfo_c_call(host, port, family, socktype, protocol = LibC::IPPROTO_IP, timeout = nil)
hints = LibC::Addrinfo.new
hints.ai_family = (family || LibC::AF_UNSPEC).to_i32
hints.ai_socktype = socktype
hints.ai_protocol = protocol
hints.ai_flags = 0

ret = LibC.getaddrinfo(host, port.to_s, pointerof(hints), out addrinfo)
raise Socket::Error.new("getaddrinfo: #{String.new(LibC.gai_strerror(ret))}") if ret != 0

begin
current_addrinfo = addrinfo
while current_addrinfo
success = yield current_addrinfo.value
break if success
current_addrinfo = current_addrinfo.value.ai_next
end
ensure
LibC.freeaddrinfo(addrinfo)
end
end

# :nodoc:
def self.getaddrinfo_libevent(host, port, family, socktype, protocol = LibC::IPPROTO_IP, timeout = nil)
hints = LibC::Addrinfo.new
hints.ai_family = (family || LibC::AF_UNSPEC).to_i32
hints.ai_socktype = socktype
1 change: 1 addition & 0 deletions src/socket/tcp_socket.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "./ip_socket"

class TCPSocket < IPSocket
# Note: dns_timeout is currently ignored
def initialize(host, port, dns_timeout = nil, connect_timeout = nil)
getaddrinfo(host, port, nil, LibC::SOCK_STREAM, LibC::IPPROTO_TCP, timeout: dns_timeout) do |addrinfo|
super(create_socket(addrinfo.ai_family, addrinfo.ai_socktype, addrinfo.ai_protocol))

0 comments on commit a3a6eac

Please sign in to comment.