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