class Bogo::Websocket::Client

Simple websocket client

Attributes

client[R]

@return [WebSocket::Frame::Incoming::Client]

connection[R]

@return [TCPSocket, OpenSSL::SSL::SSLSocket]

container[R]

@return [Thread]

control_r[R]

@return [IO]

control_w[R]

@return [IO]

die[R]

@return [TrueClass, FalseClass]

handshake[R]

@return [WebSocket::Handshake::Client]

Public Class Methods

new(args={}) click to toggle source

Create a new websocket client

@return [self]

# File lib/bogo-websocket/websocket.rb, line 45
def initialize(args={})
  load_data(args)
  @control_r, @control_w = IO.pipe
  @die = false
  setup_connection
  perform_handshake
  @lock = Mutex.new
  @container = start!
end

Public Instance Methods

build_ssl_context() click to toggle source

@return [OpenSSL::SSL::SSLContext]

# File lib/bogo-websocket/websocket.rb, line 169
def build_ssl_context
  if(ssl_context)
    ssl_context
  else
    ctx = OpenSSL::SSL::SSLContext.new
    if(ssl_key || ssl_certificate)
      ctx.cert = OpenSSL::X509::Certificate.new(File.read(ssl_certificate))
      ctx.key = OpenSSL::PKey::RSA.new(File.read(ssl_key))
    end
    ctx
  end
end
close() click to toggle source

Close the connection

# File lib/bogo-websocket/websocket.rb, line 63
def close
  if(connection)
    connection.close
    @die = true
    control_w.write 'closed'
    container.join unless Thread.current == container
    @connection = nil
  end
end
handle_message(message) click to toggle source

Handle an incoming message

@param message [WebSocket::Frame::Incoming::Client]

# File lib/bogo-websocket/websocket.rb, line 102
def handle_message(message)
  case message.type
  when :binary, :text
    on_message.call(message.data)
  when :ping
    transmit(message.data, :pong)
  when :close
    connection.close
    on_disconnect.call
  end
end
perform_handshake() click to toggle source

Setup the handshake and perform handshake with remote connection

@return [TrueClass]

# File lib/bogo-websocket/websocket.rb, line 132
def perform_handshake
  port = destination.port || destination.scheme == 'wss' ? 443 : 80
  @handshake = WebSocket::Handshake::Client.new(
    :host => destination.host,
    :port => port,
    :secure => destination.scheme == 'wss',
    :path => path,
    :query => URI.encode_www_form(params),
    :headers => headers
  )
  connection.write handshake.to_s
  reply = ''
  until(handshake.finished?)
    reply << connection.read(1)
    if(reply.index(/\r\n\r\n/m))
      handshake << reply
      reply = ''
    end
  end
  unless(handshake.valid?)
    raise ArgumentError.new 'Invalid handshake. Failed to connect!'
  end
  @client = WebSocket::Frame::Incoming::Client.new(:version => handshake.version)
  true
end
setup_connection() click to toggle source

@return [TCPSocket, OpenSSL::SSL::SSLSocket]

# File lib/bogo-websocket/websocket.rb, line 159
def setup_connection
  socket = TCPSocket.new(destination.host, destination.port)
  if(destination.scheme == 'wss')
    socket = OpenSSL::SSL::SSLSocket.new(socket, build_ssl_context)
    socket.connect
  end
  @connection = socket
end
start!() click to toggle source

Start the reader

# File lib/bogo-websocket/websocket.rb, line 74
def start!
  unless(@container)
    @container = Thread.new do
      until(die || connection.closed?)
        begin
          unless(die || connection.closed?)
            client << connection.read_nonblock(1024)
            if(message = client.next)
              handle_message(message)
            end
          end
        rescue IO::WaitReadable, Errno::EAGAIN => e
          unless(die || connection.closed?)
            IO.select([connection, control_r])
            retry
          end
        rescue => error
          on_error.call(error)
          close
        end
      end
    end
  end
end
transmit(data, type) click to toggle source

Send data to socket

@param data [String] @param type [Symbol]

# File lib/bogo-websocket/websocket.rb, line 118
def transmit(data, type)
  message = WebSocket::Frame::Outgoing::Client.new(
    :version => handshake.version,
    :data => data,
    :type => type
  )
  result = connection.write message.to_s
  connection.flush
  result
end
write(line) click to toggle source

Write to socket

@param line [String]

# File lib/bogo-websocket/websocket.rb, line 58
def write(line)
  transmit(line, :text)
end