Skip to content

Instantly share code, notes, and snippets.

@cloudvoxcode
Created July 12, 2010 17:02
Show Gist options
  • Save cloudvoxcode/472715 to your computer and use it in GitHub Desktop.
Save cloudvoxcode/472715 to your computer and use it in GitHub Desktop.
#!/usr/bin/ruby -w
# pretend to be Asterisk 1.4 (or 1.6 in 1.4 compat mode) connecting to
# a Fast AGI server, as if to process an incoming call.
#
# support: http://help.cloudvox.com/
# version: 20100815
#
# usage:
# ./asterisk_agi_test.rb some_nondefault_option=val option2=val2
# agi_ is prepended to the name of the option. connect info (path, etc) is
# taken from "request". Examples:
# ./asterisk_agi_test.rb request="agi://elsewhere.com"
# ./asterisk_agi_test.rb request="agi://elsewhere.com:4500" callerid=2065559999
require 'socket'
require 'uri'
class AgiTestClient
DEFAULTS = {
'network' => 'yes',
'request' => 'agi://localhost/app',
#'request' => 'agi://localhost/app?callback_url=http://some/url.cgi',
'channel' => 'IAX2/switch-1',
'language' => 'en',
'type' => 'IAX2',
'uniqueid' => 'instance-3-1211918167.8',
'callerid' => '2065551234',
'calleridname' => 'Test Caller',
'callingpres' => '0',
'callingani2' => '0',
'callington' => '0',
'callingtns' => '0',
'dnid' => 'unknown',
'rdnis' => 'unknown',
'context' => 'default',
'extension' => '2065550000',
'priority' => '3',
'enhanced' => '0.0',
'accountcode' => '2'
}
def place_call_as(opts)
userspec = {}
opts.collect do |opt|
opt = opt.split('=')
userspec[opt[0]] = opt[1]
end
opts = DEFAULTS.merge userspec
agi_url = URI.split opts['request']
# AGI expects the path, so take it from URL, and remove leading /
opts['network_script'] = agi_url[5][1..-1] unless opts['network_script']
host = agi_url[2]
port = agi_url[3] || 4573
puts "Connecting: #{host} #{port} #{opts['network_script']}"
@s = TCPsocket.open host, port
# order matters
%w(network request).each { |k| send_variable(k, opts[k]) }
opts.each do |k,v|
send_variable k, v
end
@s.puts "\r\n\r\n"
sleep 1
steps = [
# Adhearsion does not wait for a reply to ANSWER, so we have to
# explicitly limit the number of digits read
{ :expect => 'ANSWER',
:max_length => 6,
:send => '200 result=0' },
{ :expect => %r{EXEC swift .*new tweet.*look at me!.*},
:send => '200 result=0',
:delay => 60 },
{ :expect => 'HANGUP',
:send => '200 result=1' }
# { :expect => 'GET VARIABLE DIALED_NUMBER',
# :send => '200 result=1 (2065551234)'}
# { :expect => %r{/EXEC amd .*/},
# :send => '200 result=0' }
# { :expect => 'GET VARIABLE AMDSTATUS',
# :send => '200 result=1 (MACHINE)' }
]
begin
steps.each { |s| assert_conforms(s) }
ensure
@s.close
end
end
def assert_conforms(options)
expect = options[:expect]
send = options[:send]
delay = options[:delay] || 1
max_length = options[:max_length] || 1024
response = @s.read_nonblock max_length
if response && expect.match(response)
puts "Passed: #{response}"
sleep(delay)
@s.write("#{send}\r\n") if send
true
else
raise Exception, "Failed: #{response} (expected: #{expect})"
end
end
private
def send_variable(k,v)
@s.puts "agi_#{k}: #{v}"
end
end
if ARGV.empty?
puts 'Usage: ./asterisk_agi_test.rb request="agi://elsewhere.com" other_nondefault_agi_param="value"'
exit(-1)
end
agi_client = AgiTestClient.new
agi_client.place_call_as ARGV
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment