class Punchblock::Connection::XMPP

Attributes

event_handler[RW]
root_domain[RW]

Public Class Methods

new(options = {}) click to toggle source

Initialize the required connection attributes

@param [Hash] options @option options [String] :username client JID @option options [String] :password XMPP password @option options [String] :rayo_domain the domain on which Rayo is running @option options [Numeric, Optional] :write_timeout for which to wait on a command response @option options [Numeric, Optional] :connection_timeout for which to wait on a connection being established @option options [Numeric, nil, Optional] :ping_period interval in seconds on which to ping the server. Nil or false to disable

# File lib/punchblock/connection/xmpp.rb, line 27
def initialize(options = {})
  raise ArgumentError unless (@username = options[:username]) && options[:password]

  setup(*[:username, :password, :host, :port, :certs, :connection_timeout].map { |key| options.delete key })

  @root_domain = Blather::JID.new(options[:root_domain] || options[:rayo_domain] || @username).domain

  @joined_mixers = []

  @ping_period = options.has_key?(:ping_period) ? options[:ping_period] : 60

  Blather.logger = pb_logger
  Blather.default_log_level = :trace if Blather.respond_to? :default_log_level

  register_handlers

  super()
end

Public Instance Methods

connect() click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 86
def connect
  begin
    EM.run { client.run }
  rescue Blather::Stream::ConnectionFailed, Blather::Stream::ConnectionTimeout, Blather::StreamError => e
    raise DisconnectedError.new(e.class.to_s, e.message)
  end
end
connected?() click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 98
def connected?
  client.connected?
end
new_call_uri() click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 112
def new_call_uri
  "xmpp:#{Punchblock.new_uuid}@#{root_domain}"
end
not_ready!() click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 107
def not_ready!
  send_presence :dnd
  super
end
prep_command_for_execution(command, options = {}) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 58
def prep_command_for_execution(command, options = {})
  command.connection    = self
  command.target_call_id    ||= options[:call_id]
  command.target_mixer_name ||= options[:mixer_name]
  command.domain            ||= options[:domain]
  command.component_id      ||= options[:component_id]
  if command.is_a?(Command::Join) && command.mixer_name
    @joined_mixers << command.mixer_name
  end
  create_iq(jid_for_command(command), command.request_id).tap do |iq|
    command.to_rayo(iq)
  end
end
ready!() click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 102
def ready!
  send_presence :chat
  super
end
run() click to toggle source

Fire up the connection

# File lib/punchblock/connection/xmpp.rb, line 82
def run
  connect
end
send_message(call_id, domain, body, options = {}) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 72
def send_message(call_id, domain, body, options = {})
  jid = Blather::JID.new(call_id, domain || root_domain).to_s
  message = Blather::Stanza::Message.new(jid, body, :normal)
  message.subject = options[:subject]
  client.write message
end
stop() click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 94
def stop
  client.close if client.connected?
end
write(command, options = {}) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 46
def write(command, options = {})
  iq = prep_command_for_execution command, options
  command.request!
  client.write_with_handler iq do |response|
    if response.result?
      handle_iq_result response, command
    elsif response.error?
      handle_error response, command
    end
  end
end

Private Instance Methods

create_iq(jid, id) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 190
def create_iq(jid, id)
  Blather::Stanza::Iq.new :set, jid, id
end
handle_error(iq, command = nil) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 154
def handle_error(iq, command = nil)
  e = Blather::StanzaError.import iq
  protocol_error = ProtocolError.new.setup e.name, e.text, iq.call_id, iq.component_id
  command.response = protocol_error if command
end
handle_iq_result(iq, command) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 150
def handle_iq_result(iq, command)
  command.response = iq.rayo_node.is_a?(Ref) ? iq.rayo_node : true
end
handle_presence(p) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 136
def handle_presence(p)
  throw :pass unless p.rayo_event?
  event = p.event
  event.connection = self
  event.domain = p.from.domain
  event.transport = "xmpp"
  if @joined_mixers.include?(p.call_id)
    event.target_mixer_name = p.call_id
  else
    event.target_call_id = p.call_id
  end
  event_handler.call event
end
jid_for_command(command) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 118
def jid_for_command(command)
  return root_domain if command.is_a?(Command::Dial)

  if command.target_call_id
    node = command.target_call_id
  elsif command.target_mixer_name
    node = command.target_mixer_name
  end

  Blather::JID.new(node, command.domain || root_domain, command.component_id).to_s
end
ping_rayo() click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 180
def ping_rayo
  client.write_with_handler Blather::Stanza::Iq::Ping.new(:get, root_domain) do |response|
    begin
      handle_error response if response.is_a? Blather::BlatherError
    rescue ProtocolError => e
      raise unless e.name == :feature_not_implemented
    end
  end
end
register_handlers() click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 160
def register_handlers
  # Push a message to the queue and the log that we connected
  when_ready do
    event_handler.call Connected.new
    pb_logger.info "Connected to XMPP as #{@username}"
    @rayo_ping = EM::PeriodicTimer.new(@ping_period) { ping_rayo } if @ping_period
    throw :pass
  end

  disconnected do
    @rayo_ping.cancel if @rayo_ping
    raise DisconnectedError
  end

  # Read/handle presence requests. This is how we get events.
  presence do |msg|
    handle_presence msg
  end
end
send_presence(presence) click to toggle source
# File lib/punchblock/connection/xmpp.rb, line 130
def send_presence(presence)
  status = Blather::Stanza::Presence::Status.new presence
  status.to = root_domain
  client.write status
end