class WebSocket::Server

Public Class Methods

new(host: 'localhost', port: nil) click to toggle source
# File lib/local_server.rb, line 42
def initialize(host: 'localhost', port: nil)
  @server, @rd_pipe, @wr_pipe = TCPServer.new(host, port), *IO.pipe
end

Public Instance Methods

broadcast(message) click to toggle source
# File lib/local_server.rb, line 46
def broadcast(message)
  @wr_pipe.puts(message)
end
shutdown() click to toggle source
# File lib/local_server.rb, line 50
def shutdown
  broadcast('shutdown')

  @wr_pipe.close
  @wr_pipe = nil

  @thread.join

  @server.close
  @server = nil
end
start() click to toggle source
# File lib/local_server.rb, line 62
def start
  @thread = Thread.new do
    connections = []
    running = true
    while running
      rs, _, _ = IO.select([ @server, @rd_pipe, *connections.map { |conn| conn.socket } ])
      rs.each do |socket|
        if socket == @server
          socket = @server.accept
          begin
            connections << Connection.establish(socket)
          rescue => e
            $log.warn("Failed to perform handshake with new WebSocket client: #{e}", e)
            socket.close
          end
        elsif socket == @rd_pipe
          message = @rd_pipe.gets.chomp
          if message == 'shutdown'
            running = false
            break
          end
          $log.debug("Send ‘#{message}’ to #{connections.size} WebSocket #{connections.size == 1 ? 'client' : 'clients'}") unless connections.empty?
          connections.each do |conn|
            begin
              conn.puts(message)
            rescue => e
              $log.warn("Error writing to WebSocket client socket: #{e}")
            end
          end
        else
          if conn = connections.find { |candidate| candidate.socket == socket }
            begin
              conn.each_message do |frame|
                $log.debug("Received #{frame.to_s.size} bytes from WebSocket client: #{frame}") unless frame.to_s.empty?
              end
            rescue IO::WaitReadable
              $log.warn("IO::WaitReadable exception while reading from WebSocket client")
            rescue EOFError
              conn.socket.close
              connections.delete(conn)
            end
          end
        end
      end
    end
    @rd_pipe.close
    @rd_pipe = nil
  end
end