Created
April 22, 2015 11:57
-
-
Save marcelmorgan/1ae15a99f391603fea8b to your computer and use it in GitHub Desktop.
Handling WebSocket connections with Rack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'pusher' | |
class PlayerConnection | |
attr_reader :player, :username, :web_socket, :broadcast_id | |
def initialize(player:, web_socket:) | |
@player = player | |
@web_socket = web_socket | |
end | |
def listen | |
[:open, :close, :message].each do |event_name| | |
web_socket.on(event_name) do |event| | |
safely do | |
Rails.logger.tagged('GS') do | |
Rails.logger.info "<@#{player.to_s}:#{event_name[0]} -> #{event.data}" | |
public_send event_name, event.data | |
end | |
end | |
end | |
end | |
end | |
def message(data) | |
Router.raw_route player, Pusher, data | |
end | |
def open(data) | |
@broadcast_id = Game.broadcast.subscribe { |message| web_socket.send(message) } | |
@username = player.username | |
if Game.online[username] | |
Game.online[username] << web_socket | |
Pusher.call players_online_json, username | |
else | |
Game.online[username] = [web_socket] | |
Pusher.call players_online_json | |
end | |
end | |
def close(data) | |
Game.broadcast.unsubscribe broadcast_id | |
Game.online[username].delete(web_socket) | |
if Game.online[username].empty? | |
Game.online.delete username | |
Pusher.call players_online_json | |
end | |
end | |
def players_online_json | |
PlayersOnlineView.new(Game.online.keys).render | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'safely' | |
Game.broadcast = EM::Channel.new | |
module GameServer | |
class Backend < Struct.new(:app) | |
KEEP_ALIVE_TIME = 15 | |
def call(env) | |
if Faye::WebSocket.websocket?(env) | |
web_socket = Faye::WebSocket.new(env, nil, ping: KEEP_ALIVE_TIME) | |
player = env['warden'].authenticate(:player) | |
PlayerConnection.new(player: player, web_socket: web_socket).listen | |
# Return async Rack response | |
web_socket.rack_response | |
else | |
app.call(env) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment