class RaptorIO::Socket::TCP

TCP client socket

Constants

DEFAULT_OPTIONS

Default configuration options.

DEFAULT_SSL_OPTIONS

Default options for SSL streams connected through this socket.

@see to_ssl @see TCP::SSL

Attributes

plaintext_socket[RW]
socket[RW]

@!attribute socket

The underlying IO for this socket. Usually this is the
`socket` passed to {#initialize}
@return [IO]

Public Class Methods

new(socket, options = {}) click to toggle source

@param (see Socket#initialize)

Calls superclass method RaptorIO::Socket::new
# File lib/raptor-io/socket/tcp.rb, line 25
def initialize(socket, options = {})
  options = DEFAULT_OPTIONS.merge(options)
  super
  @plaintext_socket = @socket = socket
end

Public Instance Methods

close() click to toggle source

Close this socket. If this socket is an SSL stream, closes both the SSL stream and the underlying socket

@return [void]

Calls superclass method
# File lib/raptor-io/socket/tcp.rb, line 145
def close
  begin
    super
  ensure
    if (!@plaintext_socket.closed?)
      @plaintext_socket.close
    end
  end
end
gets(*args) click to toggle source

Ruby ‘Socket#gets` accepts:

  • ‘gets( sep = $/ )`

  • ‘gets( limit = nil )`

  • ‘gets( sep = $/, limit = nil )`

‘OpenSSL::SSL::SSLSocket#gets` however only supports `gets(sep=$/, limit=nil)`. This hack allows SSLSocket to behave the same as Ruby Socket.

@note May block

# File lib/raptor-io/socket/tcp.rb, line 126
def gets(*args)
  translate_errors do
    if args.size == 1
      arg = args.first
      if arg.is_a?(Numeric)
        @socket.gets($/, arg)
      else
        @socket.gets(arg)
      end
    else
      @socket.gets(*args)
    end
  end
end
read(maxlen) click to toggle source

Read exactly ‘maxlen` bytes from the {#socket}. If fewer than `maxlen` bytes are available for reading, wait until enough data is sent.

@note May block

@param (see read_nonblock) @return (see read_nonblock)

# File lib/raptor-io/socket/tcp.rb, line 81
def read(maxlen)
  buf = ""
  until 0 == maxlen
    prev_length = buf.length
    buf << readpartial(maxlen)
    maxlen -= buf.length - prev_length
  end
  buf
end
read_nonblock(maxlen = nil) click to toggle source

Read at most ‘maxlen` bytes from the {#socket}.

@param maxlen [Fixnum] @return [String]

# File lib/raptor-io/socket/tcp.rb, line 110
def read_nonblock(maxlen = nil)
  translate_errors do
    @socket.read_nonblock(maxlen)
  end
end
readpartial(maxlen = nil) click to toggle source

Read at most ‘maxlen` bytes from the {#socket}.

@note May block

@param (see read_nonblock) @return (see read_nonblock)

# File lib/raptor-io/socket/tcp.rb, line 97
def readpartial(maxlen = nil)
  begin
    read_nonblock(maxlen)
  rescue IO::WaitReadable
    IO.select([@socket])
    retry
  end
end
remote_address() click to toggle source
# File lib/raptor-io/socket/tcp.rb, line 46
def remote_address
  ::Addrinfo.new([ "AF_INET", options[:peer_port], options[:peer_host], options[:peer_host] ])
end
ssl?() click to toggle source

Whether this socket is encrypted with SSL

# File lib/raptor-io/socket/tcp.rb, line 163
def ssl?
  !!(@socket.respond_to?(:context) && @socket.context)
end
ssl_context() click to toggle source

@return [OpenSSL::SSL::SSLContext] @return [nil] If this socket is not SSL (see {#ssl?})

# File lib/raptor-io/socket/tcp.rb, line 179
def ssl_context
  return nil unless ssl?
  @socket.context
end
ssl_version() click to toggle source

The version of SSL/TLS that was negotiated with the server.

@return [String] See OpenSSL::SSL::SSLSocket#ssl_version for

possible values

@return [nil] If this socket is not SSL

# File lib/raptor-io/socket/tcp.rb, line 172
def ssl_version
  return nil unless ssl?
  @socket.ssl_version
end
to_io() click to toggle source

Attempt to turn this into something usable by ‘IO.select`.

@return [IO]

# File lib/raptor-io/socket/tcp.rb, line 158
def to_io
  IO.try_convert(@socket) || @socket
end
to_ssl(ssl_options = {}) click to toggle source

@note The original socket is replaced by the newly connected

{TCP::SSL} socket

Starts an SSL/TLS stream over this connection.

Using this as opposed to directly instantiating {TCP::SSL} allows you to start a TLS connection after data has already been exchanged to enable things like ‘STARTTLS`.

@note May block

@param ssl_options [Hash] Options @option ssl_options :ssl_version [Symbol] (:TLSv1) @option ssl_options :ssl_verify_mode [Constant] (OpenSSL::SSL::VERIFY_PEER)

Peer verification mode.

@option ssl_config :ssl_context [OpenSSL::SSL::SSLContext] (nil)

SSL context to use.

@return [RaptorIO::Socket::TCP::SSL] A new Socket with an established

SSL connection
# File lib/raptor-io/socket/tcp.rb, line 204
def to_ssl(ssl_options = {})
  if ssl_options[:ssl_context]
    options[:ssl_context] = ssl_options[:ssl_context]
  else
    ssl_options = DEFAULT_SSL_OPTIONS.merge(ssl_options)
    options[:ssl_context] = OpenSSL::SSL::SSLContext.new.tap do |ctx|
      ctx.ssl_version = ssl_options[:ssl_version]
      ctx.verify_mode = ssl_options[:ssl_verify_mode]
    end
  end

  s = RaptorIO::Socket::TCP::SSL.new(@plaintext_socket, options)
  @socket = s
  s
end
write(data) click to toggle source

Write ‘data` to the {#socket}.

@param data [String,#to_s] @return [Fixnum]

# File lib/raptor-io/socket/tcp.rb, line 54
def write(data)
  begin
    write_nonblock(data)
  rescue IO::WaitWritable
    IO.select(nil, [@socket])
    retry
  end
end
write_nonblock(data) click to toggle source

Try to write ‘data` to the {#socket}.

@param maxlen [Fixnum] @return [String]

# File lib/raptor-io/socket/tcp.rb, line 67
def write_nonblock(data)
  translate_errors do
    @socket.write_nonblock(data)
  end
end

Private Instance Methods

translate_errors() { || ... } click to toggle source
# File lib/raptor-io/socket/tcp.rb, line 223
def translate_errors(&block)
  yield
rescue Errno::ECONNRESET, Errno::EPIPE
  raise RaptorIO::Socket::Error::BrokenPipe
rescue Errno::ECONNREFUSED
  raise RaptorIO::Socket::Error::ConnectionRefused
end