Skip to content

Instantly share code, notes, and snippets.

@gideondk
Created November 8, 2010 22:54
Show Gist options
  • Save gideondk/668425 to your computer and use it in GitHub Desktop.
Save gideondk/668425 to your computer and use it in GitHub Desktop.
require 'rubygems'
require 'em-websocket'
require 'em-mongo'
require 'json'
require 'geokit'
require 'digest/md5'
chat_messages = []
@@session_time_out = 60 * 10
@@salt = "create-your-salt-here"
EventMachine.run {
@channel = EM::Channel.new
@collection
@db = EM::Mongo::Connection.new.db('database-name')
@message_collection = @db.collection('messages')
@session_collection = @db.collection('sessions')
@user_collection = @db.collection('users')
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 2000, :debug => false) do |ws|
def send(ws, msg)
puts msg
ws.send(msg)
end
def send_session_id(ws, msg_dict)
now = Time.now
# Search for a session
@session_collection.find({"username" => msg_dict['payload']['username'], 'time' => {'$gte' => now - @@session_time_out}}) do |res|
session_id = ""
# If no session was found, create one!
if res.count == 0
session_id = Digest::MD5.hexdigest(@@salt + Time.now.to_s + msg_dict['payload']['username'] + @@salt)
session_dict = {'username' => msg_dict['payload']['username'], 'session_id' => session_id, 'time' => now}
@session_collection.insert(session_dict)
# Else, recycle the last one
else
session_id = res[0]['session_id']
end
send ws, ({'action' => 'authenticate', 'status' => {'code' => 200, 'message' => 'Authentication successful'}, 'payload' => {'session_id' => session_id}}.to_json)
end
end
def authenticate(ws, msg_dict)
# Find given user in database
@user_collection.find({"username" => msg_dict['payload']['username']}) do |res|
fail = false
# If no users where found with the given username
if res.count == 0
puts "No results!"
fail = true
end
# If a user was found with the given username, check password
if !fail
user = res[0]
if msg_dict['payload']['password'] != user["password"]
fail = true
end
end
# If authentication failed, send error message
if fail
send ws, ({'action' => 'authenticate', 'status' => {'code' => 401, 'message' => 'User / Pass combination not valid'}}.to_json)
ws.unbind
# If success! :D
else
send_session_id ws, msg_dict
end
end
end
def create_dict_from_payload(payload, keys, add_time=true)
dict = {}
keys.each do |key|
dict[key] = payload[key]
end
if add_time
dict['time'] = Time.now
end
return dict
end
def send_session_expired_error(ws)
send ws, ({'action' => 'authenticate', 'status' => {'code' => 401, 'message' => 'Session ID not valid or expired'}}.to_json)
end
def send_message(ws, msg_dict)
now = Time.now
payload = msg_dict['payload']
@session_collection.find({"username" => payload['username'], "session_id" => payload['session_id'], 'time' => {'$gte' => now - @@session_time_out}}) do |res|
if res.count == 0
send_session_expired_error
else
@message_collection.insert(create_dict_from_payload(payload, ['message', 'location', 'session_id', 'username', 'to_username']))
send ws, ({'action' => 'message', 'status' => {'code' => 200}}.to_json)
@channel.push({'action' => 'message_push', 'payload' => create_dict_from_payload(payload, ['message', 'location', 'username', 'to_username'])}.to_json)
end
end
end
def buffer(ws, msg_dict)
payload = msg_dict['payload']
now = Time.now
@session_collection.find({"username" => payload['username'], "session_id" => payload['session_id'], 'time' => {'$gte' => now - @@session_time_out}}) do |res|
if res.count == 0
send_session_expired_error
else
@message_collection.find({}) do |res|
mes_array = []
res.each {|message| mes_array << message}
dict = {'action' => 'buffer', 'status' => {'code' => 200}, 'payload' => {'messages' => mes_array}}
send ws, dict.to_json
end
end
end
end
ws.onopen {
sid = @channel.subscribe { |msg| ws.send msg }
ws.onmessage { |msg|
msg_dict = JSON.parse msg
puts msg_dict
case msg_dict['action']
# Authenticate
when "authenticate"
puts "Authentication request"
begin
authenticate ws, msg_dict
rescue Exception => e
puts e
end
# Message
when "message"
puts "Message request"
begin
send_message ws, msg_dict
rescue Exception => e
puts e
end
# Buffer
when "buffer"
puts "Buffer request"
begin
buffer ws, msg_dict
rescue Exception => e
puts e
end
else
puts "Something else"
end
}
ws.onclose {
@channel.unsubscribe(sid)
}
}
end
# use the following command to create a user in the MongoDB databaes
# @user_collection.insert ({'username' => 'baron', 'password' => Digest::MD5.hexdigest('christmas')})
puts "Server started"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment