eric-adhearsion 0.7.999 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +8 -2
- data/EVENTS +11 -0
- data/Rakefile +96 -24
- data/adhearsion.gemspec +148 -0
- data/app_generators/ahn/ahn_generator.rb +24 -9
- data/app_generators/ahn/templates/.ahnrc +25 -3
- data/app_generators/ahn/templates/Rakefile +22 -2
- data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
- data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
- data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
- data/app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml +12 -0
- data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
- data/app_generators/ahn/templates/components/simon_game/{lib/simon_game.rb → simon_game.rb} +14 -19
- data/app_generators/ahn/templates/config/startup.rb +3 -6
- data/app_generators/ahn/templates/dialplan.rb +2 -3
- data/app_generators/ahn/templates/events.rb +32 -0
- data/bin/jahn +10 -0
- data/examples/asterisk_manager_interface/standalone.rb +51 -0
- data/lib/adhearsion.rb +17 -11
- data/lib/adhearsion/cli.rb +141 -24
- data/lib/adhearsion/component_manager.rb +169 -238
- data/lib/adhearsion/component_manager/component_tester.rb +55 -0
- data/lib/adhearsion/component_manager/spec_framework.rb +24 -0
- data/lib/adhearsion/events_support.rb +84 -0
- data/lib/adhearsion/{core_extensions → foundation}/all.rb +0 -0
- data/lib/adhearsion/{blank_slate.rb → foundation/blank_slate.rb} +0 -0
- data/lib/adhearsion/{core_extensions → foundation}/custom_daemonizer.rb +0 -0
- data/lib/adhearsion/foundation/event_socket.rb +203 -0
- data/lib/adhearsion/foundation/future_resource.rb +36 -0
- data/lib/adhearsion/{core_extensions → foundation}/global.rb +0 -0
- data/lib/adhearsion/{core_extensions → foundation}/metaprogramming.rb +0 -0
- data/lib/adhearsion/foundation/numeric.rb +13 -0
- data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
- data/lib/adhearsion/{core_extensions → foundation}/relationship_properties.rb +2 -0
- data/lib/adhearsion/foundation/string.rb +26 -0
- data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
- data/lib/adhearsion/{core_extensions → foundation}/thread_safety.rb +0 -0
- data/lib/adhearsion/host_definitions.rb +5 -1
- data/lib/adhearsion/initializer.rb +229 -73
- data/lib/adhearsion/initializer/asterisk.rb +33 -11
- data/lib/adhearsion/initializer/configuration.rb +58 -6
- data/lib/adhearsion/initializer/database.rb +3 -46
- data/lib/adhearsion/initializer/drb.rb +9 -3
- data/lib/adhearsion/initializer/freeswitch.rb +3 -3
- data/lib/adhearsion/initializer/rails.rb +1 -1
- data/lib/adhearsion/tasks.rb +2 -1
- data/lib/adhearsion/tasks/deprecations.rb +59 -0
- data/lib/adhearsion/version.rb +3 -3
- data/lib/adhearsion/voip/asterisk.rb +2 -2
- data/lib/adhearsion/voip/asterisk/agi_server.rb +9 -6
- data/lib/adhearsion/voip/asterisk/commands.rb +106 -4
- data/lib/adhearsion/voip/asterisk/manager_interface.rb +562 -0
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1754 -0
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +286 -0
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
- data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
- data/lib/adhearsion/voip/call.rb +51 -2
- data/lib/adhearsion/voip/dial_plan.rb +74 -61
- data/lib/adhearsion/voip/dsl/dialing_dsl.rb +1 -1
- data/lib/adhearsion/voip/dsl/dialplan/parser.rb +2 -6
- data/lib/adhearsion/voip/dsl/numerical_string.rb +2 -2
- data/lib/adhearsion/voip/freeswitch/oes_server.rb +2 -2
- data/lib/theatre.rb +151 -0
- data/lib/theatre/README.markdown +64 -0
- data/lib/theatre/callback_definition_loader.rb +84 -0
- data/lib/theatre/guid.rb +23 -0
- data/lib/theatre/invocation.rb +121 -0
- data/lib/theatre/namespace_manager.rb +153 -0
- data/lib/theatre/version.rb +2 -0
- metadata +63 -138
- data/Manifest.txt +0 -149
- data/README.txt +0 -6
- data/ahn_generators/component/USAGE +0 -5
- data/ahn_generators/component/component_generator.rb +0 -57
- data/ahn_generators/component/templates/configuration.rb +0 -0
- data/ahn_generators/component/templates/lib/lib.rb.erb +0 -3
- data/ahn_generators/component/templates/test/test.rb.erb +0 -12
- data/ahn_generators/component/templates/test/test_helper.rb +0 -14
- data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
- data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +0 -14
- data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +0 -31
- data/lib/adhearsion/core_extensions/array.rb +0 -0
- data/lib/adhearsion/core_extensions/guid.rb +0 -5
- data/lib/adhearsion/core_extensions/hash.rb +0 -0
- data/lib/adhearsion/core_extensions/numeric.rb +0 -4
- data/lib/adhearsion/core_extensions/proc.rb +0 -0
- data/lib/adhearsion/core_extensions/pseudo_uuid.rb +0 -11
- data/lib/adhearsion/core_extensions/publishable.rb +0 -73
- data/lib/adhearsion/core_extensions/string.rb +0 -26
- data/lib/adhearsion/core_extensions/thread.rb +0 -13
- data/lib/adhearsion/core_extensions/time.rb +0 -0
- data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
- data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
- data/lib/adhearsion/distributed/gateways/rest_gateway.rb +0 -9
- data/lib/adhearsion/distributed/gateways/soap_gateway.rb +0 -9
- data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +0 -9
- data/lib/adhearsion/distributed/peer_finder.rb +0 -0
- data/lib/adhearsion/distributed/remote_cli.rb +0 -0
- data/lib/adhearsion/hooks.rb +0 -57
- data/lib/adhearsion/initializer/paths.rb +0 -55
- data/lib/adhearsion/services/scheduler.rb +0 -5
- data/lib/adhearsion/voip/asterisk/ami.rb +0 -147
- data/lib/adhearsion/voip/asterisk/ami/actions.rb +0 -238
- data/lib/adhearsion/voip/asterisk/ami/machine.rb +0 -871
- data/lib/adhearsion/voip/asterisk/ami/machine.rl +0 -109
- data/lib/adhearsion/voip/asterisk/ami/parser.rb +0 -262
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/spec/fixtures/dialplan.rb +0 -3
- data/spec/initializer/test_configuration.rb +0 -267
- data/spec/initializer/test_loading.rb +0 -162
- data/spec/initializer/test_paths.rb +0 -43
- data/spec/silence.rb +0 -10
- data/spec/test_ahn_command.rb +0 -149
- data/spec/test_code_quality.rb +0 -87
- data/spec/test_component_manager.rb +0 -97
- data/spec/test_constants.rb +0 -8
- data/spec/test_drb.rb +0 -104
- data/spec/test_helper.rb +0 -94
- data/spec/test_hooks.rb +0 -37
- data/spec/test_host_definitions.rb +0 -79
- data/spec/test_initialization.rb +0 -105
- data/spec/test_logging.rb +0 -80
- data/spec/test_relationship_properties.rb +0 -54
- data/spec/voip/asterisk/ami_response_definitions.rb +0 -23
- data/spec/voip/asterisk/config_file_generators/test_agents.rb +0 -253
- data/spec/voip/asterisk/config_file_generators/test_queues.rb +0 -325
- data/spec/voip/asterisk/config_file_generators/test_voicemail.rb +0 -306
- data/spec/voip/asterisk/menu_command/test_calculated_match.rb +0 -111
- data/spec/voip/asterisk/menu_command/test_matchers.rb +0 -98
- data/spec/voip/asterisk/mock_ami_server.rb +0 -176
- data/spec/voip/asterisk/test_agi_server.rb +0 -451
- data/spec/voip/asterisk/test_ami.rb +0 -227
- data/spec/voip/asterisk/test_commands.rb +0 -2006
- data/spec/voip/asterisk/test_config_manager.rb +0 -129
- data/spec/voip/dsl/dispatcher_spec_helper.rb +0 -45
- data/spec/voip/dsl/test_dialing_dsl.rb +0 -268
- data/spec/voip/dsl/test_dispatcher.rb +0 -82
- data/spec/voip/dsl/test_parser.rb +0 -87
- data/spec/voip/freeswitch/test_basic_connection_manager.rb +0 -39
- data/spec/voip/freeswitch/test_inbound_connection_manager.rb +0 -39
- data/spec/voip/freeswitch/test_oes_server.rb +0 -9
- data/spec/voip/test_call_routing.rb +0 -127
- data/spec/voip/test_dialplan_manager.rb +0 -372
- data/spec/voip/test_numerical_string.rb +0 -48
- data/spec/voip/test_phone_number.rb +0 -36
- data/test/test_ahn_generator.rb +0 -59
- data/test/test_component_generator.rb +0 -52
- data/test/test_generator_helper.rb +0 -20
File without changes
|
@@ -1,14 +0,0 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__) + '/../../../../../lib'
|
2
|
-
require 'adhearsion'
|
3
|
-
require 'test/unit'
|
4
|
-
require 'flexmock/test_unit'
|
5
|
-
AHN_ROOT = Adhearsion::PathString.new(File.dirname(__FILE__) + '/../../..')
|
6
|
-
Adhearsion::ComponentManager.load
|
7
|
-
Adhearsion::ComponentManager.start
|
8
|
-
|
9
|
-
class Test::Unit::TestCase
|
10
|
-
Adhearsion::ComponentManager.components_with_call_context.each_pair do |component_class_name, component_configuration|
|
11
|
-
const_set(component_class_name, component_configuration.component_class)
|
12
|
-
const_get(component_class_name).send(:attr_accessor, :call_context)
|
13
|
-
end
|
14
|
-
end
|
File without changes
|
@@ -1,14 +0,0 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__) + '/../../../../../lib'
|
2
|
-
require 'adhearsion'
|
3
|
-
require 'test/unit'
|
4
|
-
require 'flexmock/test_unit'
|
5
|
-
AHN_ROOT = Adhearsion::PathString.new(File.dirname(__FILE__) + '/../../..')
|
6
|
-
Adhearsion::ComponentManager.load
|
7
|
-
Adhearsion::ComponentManager.start
|
8
|
-
|
9
|
-
class Test::Unit::TestCase
|
10
|
-
Adhearsion::ComponentManager.components_with_call_context.each_pair do |component_class_name, component_configuration|
|
11
|
-
const_set(component_class_name, component_configuration.component_class)
|
12
|
-
const_get(component_class_name).send(:attr_accessor, :call_context)
|
13
|
-
end
|
14
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + "/test_helper"
|
2
|
-
|
3
|
-
class TestSimonGame < Test::Unit::TestCase
|
4
|
-
attr_reader :game
|
5
|
-
def setup
|
6
|
-
@game = SimonGame.new
|
7
|
-
@game.call_context = mock_call_context
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_game_executes_say_digits_when_asked_to_say_number
|
11
|
-
flexmock(game).should_receive(:random_number).and_return("2")
|
12
|
-
mock_call_context.should_receive(:say_digits).once.with('2')
|
13
|
-
@game.say_number
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
# Didn't get very far on this
|
18
|
-
def xtest_can_play_one_round_and_receive_the_players_score
|
19
|
-
flexmock(game).should_receive(:random_number).and_return("2")
|
20
|
-
assert_equal(3, 'x')
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
def mock_call_context
|
25
|
-
@mock_call_context ||= flexmock("Mock Call Context")
|
26
|
-
end
|
27
|
-
|
28
|
-
def stub_random_number
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,73 +0,0 @@
|
|
1
|
-
module Adhearsion
|
2
|
-
class DrbDoor
|
3
|
-
|
4
|
-
include Singleton
|
5
|
-
|
6
|
-
def add(interface, name, meth)
|
7
|
-
@interfaces ||= {}
|
8
|
-
@interfaces[interface] ||= returning(Object.new) { |obj| obj.metaclass.send(:attr_accessor, :__methods) }
|
9
|
-
obj = @interfaces[interface]
|
10
|
-
obj.__methods ||= {}
|
11
|
-
obj.__methods[name] = meth
|
12
|
-
obj.instance_eval(<<-STR, __FILE__, __LINE__)
|
13
|
-
def #{name}(*args, &block)
|
14
|
-
begin
|
15
|
-
__methods["#{name}"].call(*args, &block)
|
16
|
-
rescue => exception
|
17
|
-
raise RuntimeError, exception.message, exception.backtrace
|
18
|
-
end
|
19
|
-
end
|
20
|
-
STR
|
21
|
-
end
|
22
|
-
|
23
|
-
def method_missing(name, *args, &block)
|
24
|
-
return Module.const_get(name) if name.to_s =~ /^[A-Z]/
|
25
|
-
super unless @interfaces && @interfaces.has_key?(name.to_s)
|
26
|
-
@interfaces[name.to_s]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
module Publishable
|
31
|
-
def self.included(base)
|
32
|
-
base.send(:alias_method_chain, :initialize, :publishable)
|
33
|
-
base.extend(ClassMethods)
|
34
|
-
end
|
35
|
-
|
36
|
-
def initialize_with_publishable(*args, &block)
|
37
|
-
initialize_without_publishable(*args, &block)
|
38
|
-
self.class.published_instance_methods.each do |(sym, interface)|
|
39
|
-
DrbDoor.instance.add(interface, sym.to_s, self.method(sym))
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
module ClassMethods
|
44
|
-
attr_reader :interface
|
45
|
-
attr_reader :published_instance_methods
|
46
|
-
|
47
|
-
def publish(options={}, &block)
|
48
|
-
@interface = options.delete(:through).to_s || self.to_s
|
49
|
-
begin
|
50
|
-
@capture = true
|
51
|
-
yield
|
52
|
-
ensure
|
53
|
-
@capture = false
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def method_added(sym)
|
58
|
-
return if not @capture
|
59
|
-
if sym.to_s !~ /method_added/
|
60
|
-
@published_instance_methods ||= []
|
61
|
-
@published_instance_methods << [sym, @interface]
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def singleton_method_added(sym)
|
66
|
-
return if not @capture
|
67
|
-
if sym.to_s !~ /method_added/
|
68
|
-
DrbDoor.instance.add(@interface, sym.to_s, method(sym.to_s))
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
class String
|
2
|
-
|
3
|
-
def unindent
|
4
|
-
gsub(/^\s*/,'')
|
5
|
-
end
|
6
|
-
|
7
|
-
def unindent!
|
8
|
-
gsub!(/^\s*/,'')
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.random_char
|
12
|
-
case random_digit = rand(62)
|
13
|
-
when 0...10 : random_digit.to_s
|
14
|
-
when 10...36 : (random_digit + 55).chr
|
15
|
-
when 36...62 : (random_digit + 61).chr
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.random(length_of_string=8)
|
20
|
-
Array.new(length_of_string) { random_char }.join
|
21
|
-
end
|
22
|
-
|
23
|
-
def nameify() downcase.gsub(/[^\w]/, '') end
|
24
|
-
def nameify!() replace nameify end
|
25
|
-
|
26
|
-
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/adhearsion/hooks.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Adhearsion
|
2
|
-
|
3
|
-
|
4
|
-
module Hooks
|
5
|
-
|
6
|
-
class GenericHook
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@hooks = []
|
10
|
-
end
|
11
|
-
|
12
|
-
def create_hook(&block)
|
13
|
-
@hooks.synchronize do
|
14
|
-
@hooks << block
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# TODO: This is hardly thread safe!
|
19
|
-
def trigger_hooks
|
20
|
-
@hooks.each &:call
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
class HookWithArguments < GenericHook
|
26
|
-
def trigger_hooks(*args)
|
27
|
-
@hooks.each { |hook| hook.call(*args) }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
ThreadsJoinedAfterInitialized = GenericHook.new
|
32
|
-
|
33
|
-
OnFailedCall = HookWithArguments.new
|
34
|
-
OnHungupCall = HookWithArguments.new
|
35
|
-
AfterInitialized = GenericHook.new
|
36
|
-
BeforeCall = GenericHook.new
|
37
|
-
AfterCall = GenericHook.new
|
38
|
-
TearDown = GenericHook.new
|
39
|
-
|
40
|
-
class << TearDown
|
41
|
-
def aliases
|
42
|
-
[:before_shutdown]
|
43
|
-
end
|
44
|
-
|
45
|
-
def catch_termination_signals
|
46
|
-
%w'INT TERM'.each do |sig|
|
47
|
-
trap sig do
|
48
|
-
ahn_log "Shutting down gracefully at #{Time.now}."
|
49
|
-
Adhearsion::Hooks::TearDown.trigger_hooks
|
50
|
-
exit
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
module Adhearsion
|
2
|
-
|
3
|
-
# Paths are a way for helpers to have Adhearsion manage dynamic
|
4
|
-
# paths.
|
5
|
-
module Paths
|
6
|
-
|
7
|
-
# May need to build some kind of namespacing?
|
8
|
-
|
9
|
-
@@path_managers = {}
|
10
|
-
|
11
|
-
def self.manager_for(name, hash)
|
12
|
-
globs = Array hash[:pattern] || hash[:patterns]
|
13
|
-
directory = hash[:directory]
|
14
|
-
name = name.to_s.underscore
|
15
|
-
singular, plural = name.singularize, name.pluralize
|
16
|
-
@@path_managers[singular] = globs
|
17
|
-
#TODO: YAGNI. Bad magic
|
18
|
-
Kernel.module_eval do
|
19
|
-
define_method "#{singular}_path" do |query|
|
20
|
-
target = nil
|
21
|
-
globs.each do |mgr|
|
22
|
-
Dir.glob(mgr).each do |f|
|
23
|
-
#return f if File.basename(f) == query
|
24
|
-
target = File.expand_path(f) if File.basename(f) == query
|
25
|
-
end
|
26
|
-
end
|
27
|
-
target
|
28
|
-
end
|
29
|
-
define_method "all_#{plural}" do
|
30
|
-
globs.map { |g| Dir.glob g }.flatten
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.manager_for?(name)
|
36
|
-
@@path_managers[name.to_s.underscore.singularize]
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.remove_manager_for(name)
|
40
|
-
name = name.to_s
|
41
|
-
singular, plural = name.singularize, name.pluralize
|
42
|
-
Kernel.module_eval do
|
43
|
-
undef_method "all_#{plural}", "#{singular}_path"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# When creating with a combined managers, the first
|
48
|
-
# writable directory is returned.
|
49
|
-
def self.combine_managers(name, *managers)
|
50
|
-
# TODO: Searches several managers in sequence.
|
51
|
-
name = name.to_s.underscore
|
52
|
-
singular, plural = name.singularize, name.pluralize
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,147 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'pp'
|
3
|
-
require 'yaml'
|
4
|
-
require 'socket'
|
5
|
-
require 'thread'
|
6
|
-
require 'monitor'
|
7
|
-
require 'adhearsion/voip/asterisk/ami/parser'
|
8
|
-
require 'adhearsion/voip/asterisk/ami/actions'
|
9
|
-
|
10
|
-
module Adhearsion
|
11
|
-
module VoIP
|
12
|
-
module Asterisk
|
13
|
-
class AMI
|
14
|
-
|
15
|
-
include Actions
|
16
|
-
|
17
|
-
attr_reader :action_sock, :host, :user, :password, :port, :event_thread, :scanner, :version
|
18
|
-
|
19
|
-
def initialize(user, pass, host='127.0.0.1', options={})
|
20
|
-
@host, @user, @password, @port = host, user, pass, options[:port] || 5038
|
21
|
-
@events_enabled = options[:events]
|
22
|
-
end
|
23
|
-
|
24
|
-
include Adhearsion::Publishable
|
25
|
-
|
26
|
-
publish :through => :proxy do
|
27
|
-
|
28
|
-
def originate(options={})
|
29
|
-
options[:callerid] = options.delete :caller_id if options[:caller_id]
|
30
|
-
execute_ami_command! :originate, options
|
31
|
-
end
|
32
|
-
|
33
|
-
def ping
|
34
|
-
execute_ami_command! :ping
|
35
|
-
end
|
36
|
-
|
37
|
-
# An introduction connects two endpoints together. The first argument is
|
38
|
-
# the first person the PBX will call. When she's picked up, Asterisk will
|
39
|
-
# play ringing while the second person is being dialed.
|
40
|
-
#
|
41
|
-
# The first argument is the person called first. Pass this as a canonical
|
42
|
-
# IAX2/server/user type argument. Destination takes the same format, but
|
43
|
-
# comma-separated Dial() arguments can be optionally passed after the
|
44
|
-
# technology.
|
45
|
-
#
|
46
|
-
# TODO: Provide an example when this works.
|
47
|
-
def introduce(caller, callee, opts={})
|
48
|
-
dial_args = callee
|
49
|
-
dial_args += "|#{opts[:options]}" if opts[:options]
|
50
|
-
call_and_exec caller, "Dial", :args => dial_args, :caller_id => opts[:caller_id]
|
51
|
-
end
|
52
|
-
|
53
|
-
def call_and_exec(channel, app, opts={})
|
54
|
-
args = { :channel => channel, :application => app }
|
55
|
-
args[:caller_id] = opts[:caller_id] if opts[:caller_id]
|
56
|
-
args[:data] = opts[:args] if opts[:args]
|
57
|
-
originate args
|
58
|
-
end
|
59
|
-
|
60
|
-
def call_into_context(channel, context, options={})
|
61
|
-
args = {:channel => channel, :context => context}
|
62
|
-
args[:priority] = options[:priority] || 1
|
63
|
-
args[:extension] = options[:extension] if options[:extension]
|
64
|
-
args[:caller_id] = options[:caller_id] if options[:caller_id]
|
65
|
-
if options[:variables] && options[:variables].kind_of?(Hash)
|
66
|
-
args[:variable] = options[:variables].map {|pair| pair.join('=')}.join('|')
|
67
|
-
end
|
68
|
-
originate args
|
69
|
-
end
|
70
|
-
|
71
|
-
def method_missing(name, hash={}, &block)
|
72
|
-
execute_ami_command! name, hash, &block
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
def connect!
|
78
|
-
disconnect!
|
79
|
-
start_event_thread! if events_enabled?
|
80
|
-
login! host, user, password, port, events_enabled?
|
81
|
-
end
|
82
|
-
|
83
|
-
def disconnect!
|
84
|
-
action_sock.close if action_sock && !action_sock.closed?
|
85
|
-
event_thread.kill if event_thread
|
86
|
-
scanner.stop if scanner
|
87
|
-
end
|
88
|
-
|
89
|
-
def events_enabled?
|
90
|
-
@events_enabled
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
|
95
|
-
def login!(host, user, pass, port, events)
|
96
|
-
begin
|
97
|
-
@action_sock = TCPSocket.new host, port
|
98
|
-
rescue Errno::ECONNREFUSED => refusal_error
|
99
|
-
raise Errno::ECONNREFUSED, "Could not connect with AMI to Asterisk server at #{host}:#{port}. " +
|
100
|
-
"Is enabled set to 'yes' in manager.conf?"
|
101
|
-
end
|
102
|
-
action_sock.extend(MonitorMixin)
|
103
|
-
@scanner = Parser.new
|
104
|
-
@version = scanner.run(action_sock)
|
105
|
-
begin
|
106
|
-
execute_ami_command! :login, :username => user, :secret => password, :events => (events_enabled? ? "On" : "Off")
|
107
|
-
rescue ActionError
|
108
|
-
raise AuthenticationFailedException, "Invalid AMI username/password! Check manager.conf."
|
109
|
-
else
|
110
|
-
# puts "Manager connection established to #{host}:#{port} with user '#{user}'"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def execute_ami_command!(name, options={}, &block)
|
115
|
-
action = Action.build(name, options, &block)
|
116
|
-
action_sock.synchronize do
|
117
|
-
connect! if !action_sock || action_sock.closed?
|
118
|
-
action_sock.write action.to_s
|
119
|
-
end
|
120
|
-
|
121
|
-
return unless action.has_response?
|
122
|
-
scanner.wait(action)
|
123
|
-
end
|
124
|
-
|
125
|
-
def start_event_thread!
|
126
|
-
@event_thread = Thread.new(scanner) do |scanner|
|
127
|
-
loop do
|
128
|
-
# TODO: This is totally screwed up. __read_event doesn't exist.
|
129
|
-
AMI::EventHandler.handle! __read_event(scanner.events.pop)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
event_thread.abort_on_exception = true
|
133
|
-
end
|
134
|
-
|
135
|
-
# Method simply defined as private to prevent method_missing from catching it.
|
136
|
-
def events() end
|
137
|
-
|
138
|
-
class EventHandler
|
139
|
-
# TODO: Refactor me!
|
140
|
-
end
|
141
|
-
|
142
|
-
class AuthenticationFailedException < Exception; end
|
143
|
-
class ActionError < RuntimeError; end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|