#!/usr/bin/env ruby $:.push File.join(File.dirname(__FILE__), '..', 'lib') require 'rubygems' require 'bundler/setup' require 'punchblock' require 'pry' require 'logger' require 'optparse' include Punchblock Thread.abort_on_exception = true options = { :username => 'usera@127.0.0.1', :password => '1', :wire_log_file => 'log/rayo-wire.log', :transport_log_file => 'log/rayo-transport.log', :auto_reconnect => false } option_parser = OptionParser.new do |opts| opts.banner = "Usage: punchblock-console [-u usera@127.0.0.1] [-p abc123]" opts.on("-u", "--username USERNAME", String, "Specify the XMPP JID to connect to") do |u| options[:username] = u end opts.on("-p", "--password PASSWORD", String, "Specify the XMPP password to use") do |p| options[:password] = p end opts.on("-d", "--rayo-domain DOMAIN", String, "Specify the domain Rayo is running on") do |d| options[:rayo_domain] = d end opts.on("--wire-log-file log/wirelog.log", String, "Specify the file to which the wire log should be written") do |wlf| options[:wire_log_file] = wlf end opts.on("--transport-log-file log/transportlog.log", String, "Specify the file to which the transport log should be written") do |tlf| options[:transport_log_file] = tlf end opts.on_tail("-h", "--help", "Show this message") do puts opts exit end opts.on_tail("-v", "--version", "Show version") do puts VERSION exit end end begin option_parser.parse! rescue puts $! option_parser.parse '--help' end options[:wire_logger] = Logger.new options.delete(:wire_log_file) options[:wire_logger].level = Logger::DEBUG options[:wire_logger].debug "Starting up..." options[:transport_logger] = Logger.new options.delete(:transport_log_file) options[:transport_logger].level = Logger::DEBUG options[:transport_logger].debug "Starting up..." connection = Connection.new options [:INT, :TERM].each do |signal| trap signal do puts "Shutting down!" connection.stop end end connection_thread = Thread.new do begin connection.run rescue => e puts "Exception in XMPP thread! #{e.message}" puts e.backtrace.join("\t\n") end end CALL_QUEUES = {} ### DISPATCHER THREAD # This thread multiplexes the event stream from the underlying connection handler and routes them # to the correct queue for each call. It also starts a call handler, the run_call method) after creating # the queue. Thread.new do loop do event = connection.event_queue.pop if event == connection.connected puts event puts "Waiting for a call..." next end puts "#{event.class} event for call: #{event.call_id}" case event when Event::Offer raise "Duplicate call ID for #{event.call_id}" if CALL_QUEUES.has_key?(event.call_id) CALL_QUEUES[event.call_id] = Queue.new CALL_QUEUES[event.call_id].push event run_call connection, event when Event CALL_QUEUES[event.call_id].push event else puts "Unknown event: #{event.inspect}" end end end def run_call(connection, offer) ### CALL THREAD # One thread is spun up to handle each call. Thread.new do raise "Unknown call #{offer.call_id}" unless CALL_QUEUES.has_key?(offer.call_id) queue = CALL_QUEUES[offer.call_id] call = queue.pop dsl = DSL.new connection, offer.call_id, queue puts "Incoming offer to #{offer.to} from #{offer.headers_hash[:from]} #{offer}" dsl.pry # Clean up the queue. CALL_QUEUES[offer.call_id] = nil end end connection_thread.join