class RxIO::Client

Client Class

Constants

RECONNECT_DELAY

Reconnect Delay (seconds)

SELECT_TIMEOUT

Select Timeout (seconds)

Public Class Methods

new(addr, port, service_handler, ssl = false, ssl_params = { verify_peer: true }) click to toggle source

Construct: Builds a Client around a given service_handler module, set to connect to addr on port. @param [String] addr Address to which the client should connect @param [Fixnum] port Port on which the client should connect @param [Module] service_handler Module implementing service client logic @param [Boolean] ssl Create a secure client @param [Hash] ssl_params SSL Parameters - see README

# File lib/rxio/client.rb, line 38
def initialize addr, port, service_handler, ssl = false, ssl_params = { verify_peer: true }

        # Set SSL Context
        if ssl
                @ssl_ctx = OpenSSL::SSL::SSLContext.new
                @ssl_ctx.verify_mode = ssl_params[:verify_peer] ? OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT : OpenSSL::SSL::VERIFY_NONE
        end

        # Set Address & Port
        @addr = addr
        @port = port

        # Set Service Handler Module
        @service_handler = service_handler

        # Set Socket
        @sock = nil

        # Client Hash
        @client = {
                client: self,
                local: self,
                ibuf: '',
                obuf: '',
                lock: Mutex.new,
                msgs: []
        }
end

Public Instance Methods

run() click to toggle source

Run: Executes the main client loop, taking care of I/O scheduling and message handling.

# File lib/rxio/client.rb, line 90
def run

        # Update Loop
        begin

                # Update Service
                update until @stop
        rescue Exception => e
                puts "[!] ERROR - RxIO Client Update failed - #{e.inspect}"
                e.backtrace.each { |b| puts "    - #{b}" }
        end

        # Drop Socket
        @sock.close if @sock
        @sock = nil
end
send_msg(msg) click to toggle source

Send Message: Enqueues a Message to be sent to the server. @param [String] msg

# File lib/rxio/client.rb, line 79
def send_msg msg

        # Verify Implementation
        raise "Method send_msg is not implemented by Service Handler #{@service_handler.name}" unless @service_handler.respond_to? :send_msg

        # Send Message through Service Handler
        @service_handler.send_msg @client, msg
end
set_target(addr, port) click to toggle source

Set Target: Updates the target address & port, to be used next time a connection is established. @param [String] addr @param [Fixnum] port

# File lib/rxio/client.rb, line 71
def set_target addr, port
        @addr = addr
        @port = port
end
stop() click to toggle source

Stop: Requests the client loop to stop executing. The run method should return shortly after calling stop.

# File lib/rxio/client.rb, line 110
def stop
        @stop = true
end

Private Instance Methods

ensure_sock() click to toggle source

Ensure Socket is available: Re-creates the socket in the event of failure.

# File lib/rxio/client.rb, line 134
def ensure_sock

        # Check
        return @sock if @sock

        # Reconnect Delay (don't be an asshole...)
        sleep RECONNECT_DELAY unless @sock

        # Attempt reconnect
        @sock = TCPSocket.new @addr, @port rescue nil

        # Check Socket
        return nil unless @sock

        # Wrap into SSL Socket
        if defined?(@ssl_ctx) && @ssl_ctx
                @sock = OpenSSL::SSL::SSLSocket.new @sock, @ssl_ctx
                @sock.sync_close
                @sock.connect
        end

        # Reset Client Buffers
        @client[:lock].synchronize { @client[:obuf] = '' }
        @client[:ibuf] = ''
        @client[:msgs] = []

        # Acquire Peer Address
        peer = @sock.peeraddr
        @client[:peer] = {
                port: peer[1],
                name: peer[2],
                addr: peer[3]
        }

        # Notify Service Handler on success
        @service_handler.on_join @client if @service_handler.respond_to? :on_join

        # Return Result
        @sock
end
get_endpoint_for_sock(_s) click to toggle source

Get Endpoint for Socket - Callback for IOBase: Simply returns the Client Hash. @param [TCPSocket] _s @return [Hash] The Client Hash

# File lib/rxio/client.rb, line 179
def get_endpoint_for_sock _s
        @client
end
on_drop(endpoint) click to toggle source

On Drop - Callback for IOBase: Kills the socket. @param [Hash] endpoint The Endpoint Hash

# File lib/rxio/client.rb, line 186
def on_drop endpoint
        @sock.close rescue nil
        @sock = nil
        endpoint[:peer] = nil
end
update() click to toggle source

Update: Serves as the client loop main method, performing I/O scheduling and message handling.

# File lib/rxio/client.rb, line 119
def update

        # Ensure Socket is available
        return unless ensure_sock

        # Select
        rd, wr, _er = IO.select [@sock], @client[:obuf].empty? ? [] : [@sock], [], SELECT_TIMEOUT

        # Handle I/O
        rd.each { |s| read_sock s } if rd
        wr.each { |s| write_sock s } if wr
end