lib/blather/client/client.rb in sprsquish-blather-0.3.0 vs lib/blather/client/client.rb in sprsquish-blather-0.3.1
- old
+ new
@@ -1,12 +1,12 @@
require File.join(File.dirname(__FILE__), *%w[.. .. blather])
module Blather #:nodoc:
class Client #:nodoc:
- attr_accessor :jid,
- :roster
+ attr_reader :jid,
+ :roster
def initialize
@state = :initializing
@status = Stanza::Presence::Status.new
@@ -15,10 +15,28 @@
@roster = Roster.new self
setup_initial_handlers
end
+ def jid=(new_jid)
+ @jid = JID.new new_jid
+ end
+
+ def status
+ @status.state
+ end
+
+ def status=(state)
+ state, msg, to = state
+
+ status = Stanza::Presence::Status.new state, msg
+ status.to = to
+ @status = status unless to
+
+ write status
+ end
+
def setup?
@setup.is_a? Array
end
def setup(jid, password, host = nil, port = nil)
@@ -28,102 +46,68 @@
self
end
def run
raise 'not setup!' unless setup?
- trap(:INT) { EM.stop }
- EM.run {
- klass = @setup[0].node ? Blather::Stream::Client : Blather::Stream::Component
- klass.start self, *@setup
- }
+ klass = @setup[0].node ? Blather::Stream::Client : Blather::Stream::Component
+ @stream = klass.start self, *@setup
end
def register_tmp_handler(id, &handler)
@tmp_handlers[id] = handler
end
def register_handler(type, *guards, &handler)
+ check_guards guards
@handlers[type] ||= []
@handlers[type] << [guards, handler]
end
- def status
- @status.state
- end
-
- def status=(state)
- state, msg, to = state
-
- status = Stanza::Presence::Status.new state, msg
- status.to = to
- @status = status unless to
-
- write status
- end
-
def write(stanza)
stanza.from ||= jid if stanza.respond_to?(:from)
@stream.send(stanza) if @stream
end
- def write_with_handler(stanza, &hanlder)
+ def write_with_handler(stanza, &handler)
register_tmp_handler stanza.id, &handler
write stanza
end
- def stream_started(stream)
- @stream = stream
-
- #retreive roster
- if @stream.is_a?(Stream::Component)
- @state = :ready
- call_handler_for :ready, nil
- else
- r = Stanza::Iq::Roster.new
- register_tmp_handler r.id do |node|
- roster.process node
- @state = :ready
- write @status
- call_handler_for :ready, nil
- end
- write r
+ def post_init
+ case @stream
+ when Stream::Component then ready!
+ when Stream::Client then client_post_init
+ else raise "Don't know #{@stream.class} stream type. How the hell did this happen!?"
end
end
- def stop
+ def close
@stream.close_connection_after_writing
end
- def stopped
- EM.stop
+ def unbind
+ EM.stop if EM.reactor_running?
end
- def call(stanza)
+ def receive_data(stanza)
if handler = @tmp_handlers.delete(stanza.id)
handler.call stanza
else
stanza.handler_heirarchy.each do |type|
break if call_handler_for(type, stanza) && (stanza.is_a?(BlatherError) || stanza.type == :iq)
end
end
end
- def call_handler_for(type, stanza)
- if @handlers[type]
- @handlers[type].find { |guards, handler| handler.call(stanza) unless guarded?(guards, stanza) }
- true
- end
- end
-
protected
def setup_initial_handlers
register_handler :error do |err|
raise err
end
- register_handler :iq do |iq|
- write(StanzaError.new(iq, 'service-unavailable', :cancel).to_node) if [:set, :get].include?(iq.type)
+ register_handler :iq, :type => [:get, :set] do |iq|
+ write(StanzaError.new(iq, 'service-unavailable', :cancel).to_node)
end
register_handler :status do |status|
roster[status.from].status = status if roster[status.from]
end
@@ -131,12 +115,34 @@
register_handler :roster do |node|
roster.process node
end
end
+ def ready!
+ @state = :ready
+ call_handler_for :ready, nil
+ end
+
+ def client_post_init
+ write_with_handler Stanza::Iq::Roster.new do |node|
+ roster.process node
+ write @status
+ ready!
+ end
+ end
+
+ def call_handler_for(type, stanza)
+ if @handlers[type]
+ @handlers[type].find { |guards, handler| handler.call(stanza) unless guarded?(guards, stanza) }
+ true
+ end
+ end
+
##
# If any of the guards returns FALSE this returns true
+ # the logic is reversed to allow short circuiting
+ # (why would anyone want to loop over more values than necessary?)
def guarded?(guards, stanza)
guards.find do |guard|
case guard
when Symbol
!stanza.__send__(guard)
@@ -156,11 +162,19 @@
test != value
end
end
when Proc
!guard.call(stanza)
- else
- raise "Bad guard: #{guard.inspect}"
+ end
+ end
+ end
+
+ def check_guards(guards)
+ guards.each do |guard|
+ case guard
+ when Array then guard.each { |g| check_guards([g]) }
+ when Symbol, Proc, Hash then nil
+ else raise "Bad guard: #{guard.inspect}"
end
end
end
end #Client