lib/async/io/host_endpoint.rb in async-io-1.20.0 vs lib/async/io/host_endpoint.rb in async-io-1.21.0

- old
+ new

@@ -41,19 +41,28 @@ # Try to connect to the given host by connecting to each address in sequence until a connection is made. # @yield [Socket] the socket which is being connected, may be invoked more than once # @return [Socket] the connected socket # @raise if no connection could complete successfully - def connect(&block) + def connect last_error = nil + task = Task.current + Addrinfo.foreach(*@specification) do |address| begin - return Socket.connect(address, **@options, &block) - # This is a little bit risky. In theory, what it is supposed to do is catch the failed connection, and try the next address. In practice, it can catch other kinds of failures. Ideally, it only applies to `#connect`, but it also applies to what's executed in `&block`. - rescue + wrapper = Socket.connect(address, **@options, task: task) + rescue Errno::ECONNREFUSED, Errno::ENETUNREACH, Errno::EAGAIN last_error = $! + else + return wrapper unless block_given? + + begin + return yield wrapper, task + ensure + wrapper.close + end end end raise last_error end @@ -76,16 +85,23 @@ end end end class Endpoint - # args: nodename, service, family, socktype, protocol, flags + # @param args nodename, service, family, socktype, protocol, flags. `socktype` will be set to Socket::SOCK_STREAM. + # @param options keyword arguments passed on to {HostEndpoint#initialize} + # + # @return [HostEndpoint] def self.tcp(*args, **options) args[3] = ::Socket::SOCK_STREAM HostEndpoint.new(args, **options) end + # @param args nodename, service, family, socktype, protocol, flags. `socktype` will be set to Socket::SOCK_DGRAM. + # @param options keyword arguments passed on to {HostEndpoint#initialize} + # + # @return [HostEndpoint] def self.udp(*args, **options) args[3] = ::Socket::SOCK_DGRAM HostEndpoint.new(args, **options) end