lib/socketry/tcp/socket.rb in socketry-0.3.0 vs lib/socketry/tcp/socket.rb in socketry-0.4.0

- old
+ new

@@ -5,18 +5,19 @@ module TCP # Transmission Control Protocol sockets: Provide stream-like semantics class Socket include Socketry::Timeout - attr_reader :remote_addr, :remote_port, :local_addr, :local_port + attr_reader :addr_fmaily, :remote_addr, :remote_port, :local_addr, :local_port attr_reader :read_timeout, :write_timeout, :resolver, :socket_class # Create a Socketry::TCP::Socket with the default options, then connect # to the given host. # # @param remote_addr [String] DNS name or IP address of the host to connect to # @param remote_port [Fixnum] TCP port to connect to + # # @return [Socketry::TCP::Socket] def self.connect(remote_addr, remote_port, **args) new.connect(remote_addr, remote_port, **args) end @@ -25,10 +26,11 @@ # @param read_timeout [Numeric] Seconds to wait before an uncompleted read errors # @param write_timeout [Numeric] Seconds to wait before an uncompleted write errors # @param timer [Object] A timekeeping object to use for measuring timeouts # @param resolver [Object] A resolver object to use for resolving DNS names # @param socket_class [Object] Underlying socket class which implements I/O ops + # # @return [Socketry::TCP::Socket] def initialize( read_timeout: Socketry::Timeout::DEFAULT_TIMEOUTS[:read], write_timeout: Socketry::Timeout::DEFAULT_TIMEOUTS[:write], timer: Socketry::Timeout::DEFAULT_TIMER.new, @@ -39,11 +41,11 @@ @write_timeout = write_timeout @socket_class = socket_class @resolver = resolver - @family = nil + @addr_family = nil @socket = nil @remote_addr = nil @remote_port = nil @local_addr = nil @@ -57,13 +59,14 @@ # @param remote_addr [String] DNS name or IP address of the host to connect to # @param remote_port [Fixnum] TCP port to connect to # @param local_addr [String] DNS name or IP address to bind to locally # @param local_port [Fixnum] Local TCP port to bind to # @param timeout [Numeric] Number of seconds to wait before aborting connect - # @param socket_class [Class] Custom low-level socket class + # # @raise [Socketry::AddressError] an invalid address was given # @raise [Socketry::TimeoutError] connect operation timed out + # # @return [self] def connect( remote_addr, remote_port, local_addr: nil, @@ -82,18 +85,16 @@ remote_addr = @resolver.resolve(remote_addr, timeout: time_remaining(timeout)) local_addr = @resolver.resolve(local_addr, timeout: time_remaining(timeout)) if local_addr raise ArgumentError, "expected IPAddr from resolver, got #{remote_addr.class}" unless remote_addr.is_a?(IPAddr) - if remote_addr.ipv4? - @family = ::Socket::AF_INET - elsif remote_addr.ipv6? - @family = ::Socket::AF_INET6 - else raise Socketry::AddressError, "unsupported IP address family: #{remote_addr}" - end + @addr_family = if remote_addr.ipv4? then ::Socket::AF_INET + elsif remote_addr.ipv6? then ::Socket::AF_INET6 + else raise Socketry::AddressError, "unsupported IP address family: #{remote_addr}" + end - socket = @socket_class.new(@family, ::Socket::SOCK_STREAM, 0) + socket = @socket_class.new(@addr_family, ::Socket::SOCK_STREAM, 0) socket.bind Addrinfo.tcp(local_addr.to_s, local_port) if local_addr remote_sockaddr = ::Socket.sockaddr_in(remote_port, remote_addr.to_s) # Note: `exception: false` for Socket#connect_nonblock is only supported in Ruby 2.3+ begin @@ -141,11 +142,13 @@ # Perform a non-blocking read operation # # @param size [Fixnum] number of bytes to attempt to read # @param outbuf [String, NilClass] an optional buffer into which data should be read + # # @raise [Socketry::Error] an I/O operation failed + # # @return [String, :wait_readable] data read, or :wait_readable if operation would block def read_nonblock(size, outbuf: nil) ensure_connected case outbuf when String @@ -186,11 +189,13 @@ # Read all of the data in a given string to a socket unless timeout or EOF # # @param size [Fixnum] number of bytes to attempt to read # @param outbuf [String] an output buffer to read data into # @param timeout [Numeric] Number of seconds to wait for read operation to complete + # # @raise [Socketry::Error] an I/O operation failed + # # @return [String, :eof] bytes read, or :eof if socket closed while reading def read(size, outbuf: String.new, timeout: @write_timeout) outbuf.clear deadline = lifetime + timeout if timeout @@ -210,11 +215,13 @@ end # Perform a non-blocking write operation # # @param data [String] data to write to the socket + # # @raise [Socketry::Error] an I/O operation failed + # # @return [Fixnum, :wait_writable] number of bytes written, or :wait_writable if op would block def write_nonblock(data) ensure_connected @socket.write_nonblock(data, exception: false) rescue IO::WaitWriteable @@ -247,10 +254,12 @@ # Write all of the data in a given string to a socket unless timeout or EOF # # @param data [String] data to write to the socket # @param timeout [Numeric] Number of seconds to wait for write operation to complete + # # @raise [Socketry::Error] an I/O operation failed + # # @return [Fixnum] number of bytes written, or :eof if socket closed during writing def write(data, timeout: @write_timeout) total_written = data.size deadline = lifetime + timeout if timeout