Skip to content
This repository has been archived by the owner on Jun 10, 2018. It is now read-only.

Commit

Permalink
Merge branch 'master' into apps
Browse files Browse the repository at this point in the history
Conflicts:
	lib/hector.rb
	lib/hector/concerns/authentication.rb
	lib/hector/session.rb
	test/unit/session_test.rb
  • Loading branch information
sstephenson committed Mar 12, 2010
2 parents 00253e8 + bd6d918 commit c111ddd
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 11 deletions.
3 changes: 3 additions & 0 deletions lib/hector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require "hector/errors"

require "hector/concerns/authentication"
require "hector/concerns/keep_alive"
require "hector/concerns/presence"

require "hector/commands/join"
Expand All @@ -14,6 +15,7 @@
require "hector/commands/notice"
require "hector/commands/part"
require "hector/commands/ping"
require "hector/commands/pong"
require "hector/commands/privmsg"
require "hector/commands/quit"
require "hector/commands/topic"
Expand All @@ -22,6 +24,7 @@

require "hector/channel"
require "hector/connection"
require "hector/heartbeat"
require "hector/identity"
require "hector/logging"
require "hector/request"
Expand Down
9 changes: 9 additions & 0 deletions lib/hector/commands/pong.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Hector
module Commands
module Pong
def on_pong
@received_pong = true
end
end
end
end
2 changes: 1 addition & 1 deletion lib/hector/commands/quit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Commands
module Quit
def on_quit
@quit_message = "Quit: #{request.text}"
connection.close_connection
connection.close_connection(true)
end
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/hector/concerns/authentication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def set_identity
def set_session
if @identity && @nickname
@session = UserSession.create(@nickname, self, @identity, @realname)
@session.commence_presence
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions lib/hector/concerns/keep_alive.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Hector
module Concerns
module KeepAlive
def initialize_keep_alive
@received_pong = true
@heartbeat = Hector::Heartbeat.new { on_heartbeat }
end

def on_heartbeat
if @received_pong
@received_pong = false
respond_with(:ping, Hector.server_name)
else
@quit_message = "Ping timeout"
connection.close_connection(true)
end
end

def destroy_keep_alive
@heartbeat.stop
end
end
end
end
4 changes: 2 additions & 2 deletions lib/hector/concerns/presence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ def channels
Channel.find_all_for_session(self)
end

def commence_presence
def initialize_presence
@created_at = Time.now
@updated_at = Time.now
deliver_welcome_message
end

def conclude_presence
def destroy_presence
deliver_quit_message
leave_all_channels
end
Expand Down
2 changes: 1 addition & 1 deletion lib/hector/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def receive_line(line)
if respond_to?(request.event_name)
send(request.event_name)
else
close_connection
close_connection(true)
end
end

Expand Down
25 changes: 25 additions & 0 deletions lib/hector/heartbeat.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Hector
class Heartbeat
def self.create_timer(interval, &block)
EventMachine::PeriodicTimer.new(interval, &block)
end

def initialize(interval = 60, &block)
@interval, @block = interval, block
start
end

def start
@timer ||= self.class.create_timer(@interval) { pulse }
end

def pulse
@block.call
end

def stop
@timer.cancel
@timer = nil
end
end
end
6 changes: 3 additions & 3 deletions lib/hector/session.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
module Hector
class Session
include Concerns::Presence

include Commands::Join
include Commands::Names
include Commands::Nick
include Commands::Notice
include Commands::Part
include Commands::Ping
include Commands::Pong
include Commands::Privmsg
include Commands::Quit
include Commands::Topic
Expand Down Expand Up @@ -85,7 +84,8 @@ def deliver(message_type, session, options)
end

def destroy
conclude_presence
destroy_presence
destroy_keep_alive
self.class.delete(nickname)
end

Expand Down
5 changes: 5 additions & 0 deletions lib/hector/user_session.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
module Hector
class UserSession < Session
include Concerns::KeepAlive
include Concerns::Presence

attr_reader :connection, :identity, :realname

class << self
Expand All @@ -17,6 +20,8 @@ def initialize(nickname, connection, identity, realname)
@connection = connection
@identity = identity
@realname = realname
initialize_keep_alive
initialize_presence
end

def respond_with(*)
Expand Down
53 changes: 53 additions & 0 deletions test/integration/keep_alive_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require "test_helper"

module Hector
class KeepAliveTest < IntegrationTest
test :"keep-alive ping is sent on pulse" do
authenticated_connection.tap do |c|
assert_not_sent_to c, "PING hector.irc"
assert_sent_to c, "PING hector.irc" do
pulse(c)
end
assert !c.connection_closed?
end
end

test :"responding with pong results in another ping on the next pulse" do
authenticated_connection.tap do |c|
pulse(c)
c.receive_line "PONG hector.irc"
assert_sent_to c, "PING hector.irc" do
pulse(c)
end
assert !c.connection_closed?
end
end

test :"not responding with pong results in disconnection on the next pulse" do
authenticated_connection.tap do |c|
pulse(c)
assert_not_sent_to c, "PING hector.irc" do
pulse(c)
end
assert c.connection_closed?
end
end

test :"channel members are notified of keep-alive timeouts" do
authenticated_connections(:join => "#test") do |c1, c2|
pulse(c1)
assert_sent_to c2, ":user1!sam@hector.irc QUIT" do
pulse(c1)
end
end
end

def pulse(connection)
heartbeat(connection).pulse
end

def heartbeat(connection)
connection.session.instance_variable_get(:@heartbeat)
end
end
end
9 changes: 9 additions & 0 deletions test/lib/hector/test_heartbeat.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Hector
class Heartbeat
def self.create_timer(interval)
Object.new.tap do |o|
def o.cancel; end
end
end
end
end
2 changes: 2 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

require "hector/test_case"
require "hector/test_connection"
require "hector/test_heartbeat"
require "hector/integration_test"

module Hector
Expand All @@ -28,3 +29,4 @@ def self.fixture_path(filename)
IDENTITY_FIXTURES = fixture_path("identities.yml")
Identity.adapter = YamlIdentityAdapter.new(IDENTITY_FIXTURES)
end

4 changes: 1 addition & 3 deletions test/unit/session_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,7 @@ def teardown
end

def create_session(nickname)
UserSession.create(nickname, connection, identity, "Real Name").tap do |session|
session.commence_presence
end
UserSession.create(nickname, connection, identity, "Real Name")
end

def session_names
Expand Down

0 comments on commit c111ddd

Please sign in to comment.