eric-adhearsion 0.7.999

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. data/CHANGELOG +3 -0
  2. data/LICENSE +456 -0
  3. data/Manifest.txt +149 -0
  4. data/README.txt +6 -0
  5. data/Rakefile +48 -0
  6. data/ahn_generators/component/USAGE +5 -0
  7. data/ahn_generators/component/component_generator.rb +57 -0
  8. data/ahn_generators/component/templates/configuration.rb +0 -0
  9. data/ahn_generators/component/templates/lib/lib.rb.erb +3 -0
  10. data/ahn_generators/component/templates/test/test.rb.erb +12 -0
  11. data/ahn_generators/component/templates/test/test_helper.rb +14 -0
  12. data/app_generators/ahn/USAGE +5 -0
  13. data/app_generators/ahn/ahn_generator.rb +76 -0
  14. data/app_generators/ahn/templates/.ahnrc +12 -0
  15. data/app_generators/ahn/templates/README +8 -0
  16. data/app_generators/ahn/templates/Rakefile +3 -0
  17. data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
  18. data/app_generators/ahn/templates/components/simon_game/lib/simon_game.rb +61 -0
  19. data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +14 -0
  20. data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +31 -0
  21. data/app_generators/ahn/templates/config/startup.rb +53 -0
  22. data/app_generators/ahn/templates/dialplan.rb +4 -0
  23. data/bin/ahn +28 -0
  24. data/bin/ahnctl +68 -0
  25. data/bin/jahn +32 -0
  26. data/lib/adhearsion/blank_slate.rb +5 -0
  27. data/lib/adhearsion/cli.rb +106 -0
  28. data/lib/adhearsion/component_manager.rb +277 -0
  29. data/lib/adhearsion/core_extensions/all.rb +9 -0
  30. data/lib/adhearsion/core_extensions/array.rb +0 -0
  31. data/lib/adhearsion/core_extensions/custom_daemonizer.rb +45 -0
  32. data/lib/adhearsion/core_extensions/global.rb +1 -0
  33. data/lib/adhearsion/core_extensions/guid.rb +5 -0
  34. data/lib/adhearsion/core_extensions/hash.rb +0 -0
  35. data/lib/adhearsion/core_extensions/metaprogramming.rb +17 -0
  36. data/lib/adhearsion/core_extensions/numeric.rb +4 -0
  37. data/lib/adhearsion/core_extensions/proc.rb +0 -0
  38. data/lib/adhearsion/core_extensions/pseudo_uuid.rb +11 -0
  39. data/lib/adhearsion/core_extensions/publishable.rb +73 -0
  40. data/lib/adhearsion/core_extensions/relationship_properties.rb +40 -0
  41. data/lib/adhearsion/core_extensions/string.rb +26 -0
  42. data/lib/adhearsion/core_extensions/thread.rb +13 -0
  43. data/lib/adhearsion/core_extensions/thread_safety.rb +7 -0
  44. data/lib/adhearsion/core_extensions/time.rb +0 -0
  45. data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
  46. data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
  47. data/lib/adhearsion/distributed/gateways/rest_gateway.rb +9 -0
  48. data/lib/adhearsion/distributed/gateways/soap_gateway.rb +9 -0
  49. data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +9 -0
  50. data/lib/adhearsion/distributed/peer_finder.rb +0 -0
  51. data/lib/adhearsion/distributed/remote_cli.rb +0 -0
  52. data/lib/adhearsion/hooks.rb +57 -0
  53. data/lib/adhearsion/host_definitions.rb +63 -0
  54. data/lib/adhearsion/initializer/asterisk.rb +59 -0
  55. data/lib/adhearsion/initializer/configuration.rb +202 -0
  56. data/lib/adhearsion/initializer/database.rb +92 -0
  57. data/lib/adhearsion/initializer/drb.rb +25 -0
  58. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  59. data/lib/adhearsion/initializer/paths.rb +55 -0
  60. data/lib/adhearsion/initializer/rails.rb +40 -0
  61. data/lib/adhearsion/initializer.rb +217 -0
  62. data/lib/adhearsion/logging.rb +92 -0
  63. data/lib/adhearsion/services/scheduler.rb +5 -0
  64. data/lib/adhearsion/tasks/database.rb +5 -0
  65. data/lib/adhearsion/tasks/generating.rb +20 -0
  66. data/lib/adhearsion/tasks/lint.rb +4 -0
  67. data/lib/adhearsion/tasks/testing.rb +37 -0
  68. data/lib/adhearsion/tasks.rb +15 -0
  69. data/lib/adhearsion/version.rb +9 -0
  70. data/lib/adhearsion/voip/asterisk/agi_server.rb +78 -0
  71. data/lib/adhearsion/voip/asterisk/ami/actions.rb +238 -0
  72. data/lib/adhearsion/voip/asterisk/ami/machine.rb +871 -0
  73. data/lib/adhearsion/voip/asterisk/ami/machine.rl +109 -0
  74. data/lib/adhearsion/voip/asterisk/ami/parser.rb +262 -0
  75. data/lib/adhearsion/voip/asterisk/ami.rb +147 -0
  76. data/lib/adhearsion/voip/asterisk/commands.rb +1182 -0
  77. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  78. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  79. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  80. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  81. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  82. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  83. data/lib/adhearsion/voip/asterisk.rb +4 -0
  84. data/lib/adhearsion/voip/call.rb +391 -0
  85. data/lib/adhearsion/voip/call_routing.rb +64 -0
  86. data/lib/adhearsion/voip/commands.rb +9 -0
  87. data/lib/adhearsion/voip/constants.rb +39 -0
  88. data/lib/adhearsion/voip/conveniences.rb +18 -0
  89. data/lib/adhearsion/voip/dial_plan.rb +205 -0
  90. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  91. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  92. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  93. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  94. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +75 -0
  95. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  96. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  97. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  98. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  99. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  100. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  101. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  102. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  103. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  104. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  105. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  106. data/lib/adhearsion.rb +31 -0
  107. data/script/destroy +14 -0
  108. data/script/generate +14 -0
  109. data/spec/fixtures/dialplan.rb +3 -0
  110. data/spec/initializer/test_configuration.rb +267 -0
  111. data/spec/initializer/test_loading.rb +162 -0
  112. data/spec/initializer/test_paths.rb +43 -0
  113. data/spec/silence.rb +10 -0
  114. data/spec/test_ahn_command.rb +149 -0
  115. data/spec/test_code_quality.rb +87 -0
  116. data/spec/test_component_manager.rb +97 -0
  117. data/spec/test_constants.rb +8 -0
  118. data/spec/test_drb.rb +104 -0
  119. data/spec/test_helper.rb +94 -0
  120. data/spec/test_hooks.rb +37 -0
  121. data/spec/test_host_definitions.rb +79 -0
  122. data/spec/test_initialization.rb +105 -0
  123. data/spec/test_logging.rb +80 -0
  124. data/spec/test_relationship_properties.rb +54 -0
  125. data/spec/voip/asterisk/ami_response_definitions.rb +23 -0
  126. data/spec/voip/asterisk/config_file_generators/test_agents.rb +253 -0
  127. data/spec/voip/asterisk/config_file_generators/test_queues.rb +325 -0
  128. data/spec/voip/asterisk/config_file_generators/test_voicemail.rb +306 -0
  129. data/spec/voip/asterisk/menu_command/test_calculated_match.rb +111 -0
  130. data/spec/voip/asterisk/menu_command/test_matchers.rb +98 -0
  131. data/spec/voip/asterisk/mock_ami_server.rb +176 -0
  132. data/spec/voip/asterisk/test_agi_server.rb +451 -0
  133. data/spec/voip/asterisk/test_ami.rb +227 -0
  134. data/spec/voip/asterisk/test_commands.rb +2006 -0
  135. data/spec/voip/asterisk/test_config_manager.rb +129 -0
  136. data/spec/voip/dsl/dispatcher_spec_helper.rb +45 -0
  137. data/spec/voip/dsl/test_dialing_dsl.rb +268 -0
  138. data/spec/voip/dsl/test_dispatcher.rb +82 -0
  139. data/spec/voip/dsl/test_parser.rb +87 -0
  140. data/spec/voip/freeswitch/test_basic_connection_manager.rb +39 -0
  141. data/spec/voip/freeswitch/test_inbound_connection_manager.rb +39 -0
  142. data/spec/voip/freeswitch/test_oes_server.rb +9 -0
  143. data/spec/voip/test_call_routing.rb +127 -0
  144. data/spec/voip/test_dialplan_manager.rb +372 -0
  145. data/spec/voip/test_numerical_string.rb +48 -0
  146. data/spec/voip/test_phone_number.rb +36 -0
  147. data/test/test_ahn_generator.rb +59 -0
  148. data/test/test_component_generator.rb +52 -0
  149. data/test/test_generator_helper.rb +20 -0
  150. metadata +254 -0
@@ -0,0 +1,217 @@
1
+ module Adhearsion
2
+
3
+ class PathString < String
4
+ attr_accessor :component_path, :dialplan_path, :log_path
5
+
6
+ def initialize(path)
7
+ super
8
+ defaults
9
+ end
10
+
11
+ def defaults
12
+ @component_path = build_path_for "components"
13
+ @dialplan_path = dup
14
+ @log_path = build_path_for "logs"
15
+ end
16
+
17
+ def base_path=(value)
18
+ replace(value)
19
+ defaults
20
+ end
21
+
22
+ def using_base_path(temporary_base_path, &block)
23
+ original_path = dup
24
+ self.base_path = temporary_base_path
25
+ block.call
26
+ ensure
27
+ self.base_path = original_path
28
+ end
29
+
30
+ def dial_plan_named(name)
31
+ File.join(dialplan_path, name)
32
+ end
33
+
34
+ private
35
+ def build_path_for(path)
36
+ File.join(to_s, path)
37
+ end
38
+ end
39
+
40
+ class Initializer
41
+
42
+ class << self
43
+ def get_rules_from(location)
44
+ if File.directory? location
45
+ location = File.join location, ".ahnrc"
46
+ end
47
+ File.exists?(location) ? YAML.load_file(location) : nil
48
+ end
49
+
50
+ def ahn_root=(path)
51
+ if Object.constants.include?("AHN_ROOT")
52
+ Object.const_get(:AHN_ROOT).base_path = File.expand_path(path)
53
+ else
54
+ Object.const_set(:AHN_ROOT, PathString.new(File.expand_path(path)))
55
+ end
56
+ end
57
+
58
+ def start_from_init_file(file, ahn_app_path)
59
+ return if defined?(@@started) && @@started
60
+ new(ahn_app_path, :loaded_init_files => file)
61
+ end
62
+
63
+ end
64
+
65
+ attr_reader :path, :daemon, :pid_file, :log_file, :ahn_app_log_directory
66
+
67
+ DEFAULT_RULES = { :pattern => "*.rb",
68
+ :directory => "helpers"}
69
+
70
+ # Creation of pid_files
71
+ #
72
+ # - You may want to have Adhearsion create a process identification
73
+ # file when it boots so that a crash monitoring program such as
74
+ # Monit can reboot if necessary or so the init script can kill it
75
+ # for system shutdowns.
76
+ # - To have Adhearsion create a pid file in the default location (i.e.
77
+ # AHN_INSTALL_DIR/adhearsion.pid), supply :pid_file with 'true'. Otherwise
78
+ # one is not created UNLESS it is running in daemon mode, in which
79
+ # case one is created. You can force Adhearsion to not create one
80
+ # even in daemon mode by supplying "false".
81
+ def initialize(path=nil, options={})
82
+ @@started = true
83
+ @path = path
84
+ @daemon = options[:daemon]
85
+ @pid_file = options[:pid_file].nil? ? ENV['PID_FILE'] : options[:pid_file]
86
+ @loaded_init_files = options[:loaded_init_files]
87
+ self.class.ahn_root = path
88
+ resolve_pid_file_path
89
+ resolve_log_file_path
90
+ switch_to_root_directory
91
+ catch_termination_signal
92
+ bootstrap_rc
93
+ load_all_init_files
94
+ init_modules
95
+ daemonize! if should_daemonize?
96
+ initialize_log_file
97
+ create_pid_file if pid_file
98
+ load_components
99
+
100
+ ahn_log "Adhearsion initialized!"
101
+
102
+ trigger_after_initialized_hooks
103
+ join_framework_threads
104
+ end
105
+
106
+ def initialize_log_file
107
+ Dir.mkdir(ahn_app_log_directory) unless File.directory? ahn_app_log_directory
108
+ file_logger = Log4r::FileOutputter.new("Main Adhearsion log file", :filename => log_file, :trunc => false)
109
+
110
+ if should_daemonize?
111
+ Adhearsion::Logging::AdhearsionLogger.outputters = file_logger
112
+ else
113
+ Adhearsion::Logging::AdhearsionLogger.outputters << file_logger
114
+ end
115
+ Adhearsion::Logging::DefaultAdhearsionLogger.redefine_outputters
116
+ end
117
+
118
+ def resolve_log_file_path
119
+ @ahn_app_log_directory = AHN_ROOT + '/log'
120
+ @log_file = File.expand_path(ahn_app_log_directory + "/adhearsion.log")
121
+ end
122
+
123
+ def create_pid_file(file = pid_file)
124
+ if file
125
+ File.open pid_file, 'w' do |file|
126
+ file.puts Process.pid
127
+ end
128
+
129
+ Hooks::TearDown.create_hook do
130
+ File.delete(pid_file) if File.exists?(pid_file)
131
+ end
132
+ end
133
+ end
134
+
135
+ def init_modules
136
+ require 'adhearsion/initializer/database.rb'
137
+ require 'adhearsion/initializer/asterisk.rb'
138
+ require 'adhearsion/initializer/drb.rb'
139
+ require 'adhearsion/initializer/rails.rb'
140
+ # require 'adhearsion/initializer/freeswitch.rb'
141
+
142
+ DatabaseInitializer.start if AHN_CONFIG.database_enabled?
143
+ AsteriskInitializer.start if AHN_CONFIG.asterisk_enabled?
144
+ DrbInitializer.start if AHN_CONFIG.drb_enabled?
145
+ RailsInitializer.start if AHN_CONFIG.rails_enabled?
146
+ # FreeswitchInitializer.start if AHN_CONFIG.freeswitch_enabled?
147
+ end
148
+
149
+ def resolve_pid_file_path
150
+ @pid_file = if pid_file.equal?(true) then default_pid_path
151
+ elsif pid_file then pid_file
152
+ elsif pid_file.equal?(false) then nil
153
+ # FIXME @pid_file = @daemon? Assignment or equality? I'm assuming equality.
154
+ else @pid_file = @daemon ? default_pid_path : nil
155
+ end
156
+ end
157
+
158
+ def switch_to_root_directory
159
+ Dir.chdir AHN_ROOT
160
+ end
161
+
162
+ def catch_termination_signal
163
+ Hooks::TearDown.catch_termination_signals
164
+ end
165
+
166
+ def load_all_init_files
167
+ if Paths.manager_for? "init"
168
+ init_files_from_rc = all_inits.map { |file| File.expand_path(file) }
169
+ already_loaded_init_files = Array(@loaded_init_files).map { |file| File.expand_path(file) }
170
+ (init_files_from_rc - already_loaded_init_files).each { |init| load init }
171
+ end
172
+ end
173
+
174
+ def should_daemonize?
175
+ @daemon || ENV['DAEMON']
176
+ end
177
+
178
+ def daemonize!
179
+ ahn_log "Daemonizing now! Creating #{pid_file}."
180
+ extend Adhearsion::CustomDaemonizer
181
+ daemonize log_file
182
+ end
183
+
184
+ def load_components
185
+ ComponentManager.load
186
+ ComponentManager.start
187
+ end
188
+
189
+ def trigger_after_initialized_hooks
190
+ Hooks::AfterInitialized.trigger_hooks
191
+ end
192
+
193
+ def join_framework_threads
194
+ Hooks::ThreadsJoinedAfterInitialized.trigger_hooks
195
+ end
196
+
197
+ def bootstrap_rc
198
+ rules = Initializer.get_rules_from(AHN_ROOT) || DEFAULT_RULES
199
+ paths = rules['paths'] || DEFAULT_RULES
200
+ paths.each_pair do |k,v|
201
+ if v.kind_of? Hash
202
+ directory, pattern = v['directory'] || '.', v['pattern'] || '*'
203
+ Paths.manager_for k, :pattern => File.join(directory, pattern)
204
+ else
205
+ directory, pattern = '.', v
206
+ Paths.manager_for k, :pattern => File.join(directory,pattern)
207
+ end
208
+ end
209
+ end
210
+
211
+ def default_pid_path
212
+ File.join AHN_ROOT, 'adhearsion.pid'
213
+ end
214
+
215
+ class InitializationFailedError < Exception; end
216
+ end
217
+ end
@@ -0,0 +1,92 @@
1
+ require 'log4r'
2
+
3
+ module Adhearsion
4
+ module Logging
5
+
6
+ @@logging_level_lock = Mutex.new
7
+
8
+ class << self
9
+
10
+ def silence!
11
+ self.logging_level = :fatal
12
+ end
13
+
14
+ def unsilence!
15
+ self.logging_level = :info
16
+ end
17
+
18
+ def logging_level=(new_logging_level)
19
+ new_logging_level = Log4r.const_get(new_logging_level.to_s.upcase)
20
+ @@logging_level_lock.synchronize do
21
+ @@logging_level = new_logging_level
22
+ Log4r::Logger.each_logger do |logger|
23
+ logger.level = new_logging_level
24
+ end
25
+ end
26
+ end
27
+
28
+ def logging_level
29
+ @@logging_level_lock.synchronize do
30
+ return @@logging_level ||= Log4r::INFO
31
+ end
32
+ end
33
+ end
34
+
35
+ class AdhearsionLogger < Log4r::Logger
36
+
37
+ @@outputters = [Log4r::Outputter.stdout]
38
+
39
+ class << self
40
+ def outputters
41
+ @@outputters
42
+ end
43
+
44
+ def outputters=(other)
45
+ @@outputters = other
46
+ end
47
+ end
48
+
49
+ def initialize(*args)
50
+ super
51
+ redefine_outputters
52
+ end
53
+
54
+ def redefine_outputters
55
+ self.outputters = @@outputters
56
+ end
57
+
58
+ def method_missing(logger_name, *args, &block)
59
+ define_logging_method(logger_name, self.class.new(logger_name.to_s))
60
+ send(logger_name, *args, &block)
61
+ end
62
+
63
+ private
64
+
65
+ def define_logging_method(name, logger)
66
+ # Can't use Module#define_method() because blocks in Ruby 1.8.x can't
67
+ # have their own block arguments.
68
+ self.class.class_eval(<<-CODE, __FILE__, __LINE__)
69
+ def #{name}(*args, &block)
70
+ logger = Log4r::Logger['#{name}']
71
+ if args.any? || block_given?
72
+ logger.info(*args, &block)
73
+ else
74
+ logger
75
+ end
76
+ end
77
+ CODE
78
+ end
79
+ end
80
+
81
+ DefaultAdhearsionLogger = AdhearsionLogger.new 'ahn'
82
+
83
+ end
84
+ end
85
+
86
+ def ahn_log(*args)
87
+ if args.any?
88
+ Adhearsion::Logging::DefaultAdhearsionLogger.info(*args)
89
+ else
90
+ Adhearsion::Logging::DefaultAdhearsionLogger
91
+ end
92
+ end
@@ -0,0 +1,5 @@
1
+ module Adhearsion
2
+ module Scheduler
3
+
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ task:migrate do
2
+ require 'active_record'
3
+ %w.db/migrate db/ahn..each
4
+ ActiveRecord::Migrator.migrate 'db/migrate', ENV['VERSION'] ? ENV['VERSION'].to_i : nil
5
+ end
@@ -0,0 +1,20 @@
1
+ namespace:create do
2
+
3
+ task:war do
4
+ # Hmm, this will is a tough one
5
+ end
6
+
7
+ task:rails_plugin do
8
+
9
+ end
10
+
11
+ task:migration do
12
+ name = ARGV.shift
13
+ end
14
+ end
15
+
16
+ namespace:delete do
17
+ task:migration do
18
+ # Take arg.underscore and remove it
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ task :sanity do
2
+ puts "Performing many checks on your Adhearsion application!"
3
+ # TODO: Anything that should be brought to the user's attention should be placed here!
4
+ end
@@ -0,0 +1,37 @@
1
+ namespace:test do
2
+ desc "Run tests for a component specified by COMPONENT=<component_name>. If no component is specified, tests will be executed for all components"
3
+ task :component do
4
+ component = ENV['COMPONENT']
5
+ components_to_test = component.nil? ? all_component_directories : [full_path_for(component)]
6
+ components_to_test.each do |component_name|
7
+ setup_and_execute(component_name)
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def setup_and_execute(component_path)
14
+ task = create_test_task_for(component_path)
15
+ Rake::Task[task.name].execute
16
+ end
17
+
18
+ def create_test_task_for(component_path)
19
+ Rake::TestTask.new(task_name_for(component_path)) do |t|
20
+ t.libs = ["lib", "test"].map{|subdir| File.join(component_path, subdir)}
21
+ t.test_files = FileList["#{component_path}/test/test_*.rb"]
22
+ t.verbose = true
23
+ end
24
+ end
25
+
26
+ def task_name_for(component_path)
27
+ "test_#{component_path.split(/\//).last}"
28
+ end
29
+
30
+ def all_component_directories
31
+ Dir['components/*']
32
+ end
33
+
34
+ def full_path_for(component)
35
+ component =~ /^components\// ? component : File.join("components", component)
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ require 'rake/testtask'
2
+ require 'adhearsion'
3
+ require 'adhearsion/tasks/database'
4
+ require 'adhearsion/tasks/testing'
5
+ require 'adhearsion/tasks/generating'
6
+ require 'adhearsion/tasks/lint'
7
+
8
+ namespace :adhearsion do
9
+ desc "Dump useful information about this application's adhearsion environment"
10
+ task :about do
11
+ puts "Adhearsion version: #{Adhearsion::VERSION::STRING}"
12
+ end
13
+ end
14
+
15
+ task :default => "adhearsion:about"
@@ -0,0 +1,9 @@
1
+ module Adhearsion #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0 unless defined? MAJOR
4
+ MINOR = 7 unless defined? MINOR
5
+ TINY = 999 unless defined? TINY
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.') unless defined? STRING
8
+ end
9
+ end
@@ -0,0 +1,78 @@
1
+ require 'gserver'
2
+ module Adhearsion
3
+ module VoIP
4
+ module Asterisk
5
+ module AGI
6
+ class Server
7
+
8
+ class RubyServer < GServer
9
+
10
+ def initialize(port, host)
11
+ super(port, host, (1.0/0.0)) # (1.0/0.0) == Infinity
12
+ end
13
+
14
+ def serve(io)
15
+ Hooks::BeforeCall.trigger_hooks
16
+ call = Adhearsion.receive_call_from(io)
17
+ ahn_log.agi "Handling call with variables #{call.variables.inspect}"
18
+
19
+ return DialPlan::ConfirmationManager.handle(call) if DialPlan::ConfirmationManager.confirmation_call?(call)
20
+
21
+ # This is what happens 99.9% of the time.
22
+
23
+ DialPlan::Manager.handle call
24
+ rescue DialPlan::Manager::NoContextError => e
25
+ ahn_log.agi e.message
26
+ call.hangup!
27
+ rescue FailedExtensionCallException => failed_call
28
+ begin
29
+ ahn_log.agi "Received \"failed\" meta-call with :failed_reason => #{failed_call.call.failed_reason.inspect}. Executing OnFailedCall hooks."
30
+ Hooks::OnFailedCall.trigger_hooks(failed_call.call)
31
+ call.hangup!
32
+ rescue => e
33
+ ahn_log.agi.error e
34
+ end
35
+ rescue HungupExtensionCallException => hungup_call
36
+ begin
37
+ ahn_log.agi "Received \"h\" meta-call. Executing OnHungupCall hooks."
38
+ Hooks::OnHungupCall.trigger_hooks(hungup_call.call)
39
+ call.hangup!
40
+ rescue => e
41
+ ahn_log.agi.error e
42
+ end
43
+ rescue UselessCallException
44
+ ahn_log.agi "Ignoring meta-AGI request"
45
+ call.hangup!
46
+ # TBD: (may have more hooks than what Jay has defined in hooks.rb)
47
+ rescue => e
48
+ ahn_log.agi.error e.inspect
49
+ ahn_log.agi.error e.backtrace.map { |s| " " * 5 + s }.join("\n")
50
+ end
51
+ end
52
+
53
+ DEFAULT_OPTIONS = { :server_class => RubyServer, :port => 4573, :host => "0.0.0.0" } unless defined? DEFAULT_OPTIONS
54
+ attr_reader :host, :port, :server_class, :server
55
+
56
+ def initialize(options = {})
57
+ options = DEFAULT_OPTIONS.merge options
58
+ @host, @port, @server_class = options.values_at(:host, :port, :server_class)
59
+ @server = server_class.new(port, host)
60
+ end
61
+
62
+ def start
63
+ server.start
64
+ end
65
+
66
+ def shutdown
67
+ server.stop
68
+ end
69
+
70
+ def join
71
+ server.join
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end