adhearsion 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/CHANGELOG +11 -2
  2. data/EVENTS +1 -1
  3. data/Rakefile +4 -4
  4. data/adhearsion.gemspec +8 -4
  5. data/app_generators/ahn/USAGE +3 -3
  6. data/app_generators/ahn/ahn_generator.rb +11 -11
  7. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +3 -3
  8. data/app_generators/ahn/templates/components/disabled/restful_rpc/example-client.rb +6 -6
  9. data/app_generators/ahn/templates/components/disabled/restful_rpc/restful_rpc.rb +16 -16
  10. data/app_generators/ahn/templates/components/disabled/restful_rpc/spec/restful_rpc_spec.rb +42 -42
  11. data/app_generators/ahn/templates/components/disabled/sandbox/sandbox.rb +11 -11
  12. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +1 -1
  13. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +6 -6
  14. data/app_generators/ahn/templates/components/simon_game/simon_game.rb +4 -4
  15. data/app_generators/ahn/templates/config/startup.rb +31 -16
  16. data/bin/ahn +3 -3
  17. data/bin/ahnctl +8 -8
  18. data/bin/jahn +3 -3
  19. data/examples/asterisk_manager_interface/standalone.rb +2 -2
  20. data/lib/adhearsion.rb +4 -2
  21. data/lib/adhearsion/cli.rb +31 -31
  22. data/lib/adhearsion/component_manager.rb +39 -39
  23. data/lib/adhearsion/component_manager/component_tester.rb +14 -14
  24. data/lib/adhearsion/component_manager/spec_framework.rb +1 -1
  25. data/lib/adhearsion/events_support.rb +12 -12
  26. data/lib/adhearsion/foundation/blank_slate.rb +1 -1
  27. data/lib/adhearsion/foundation/custom_daemonizer.rb +2 -2
  28. data/lib/adhearsion/foundation/event_socket.rb +26 -26
  29. data/lib/adhearsion/foundation/future_resource.rb +6 -6
  30. data/lib/adhearsion/foundation/metaprogramming.rb +2 -2
  31. data/lib/adhearsion/foundation/numeric.rb +3 -3
  32. data/lib/adhearsion/foundation/relationship_properties.rb +7 -7
  33. data/lib/adhearsion/foundation/string.rb +8 -8
  34. data/lib/adhearsion/foundation/synchronized_hash.rb +8 -8
  35. data/lib/adhearsion/host_definitions.rb +16 -16
  36. data/lib/adhearsion/initializer.rb +74 -65
  37. data/lib/adhearsion/initializer/asterisk.rb +15 -9
  38. data/lib/adhearsion/initializer/configuration.rb +54 -39
  39. data/lib/adhearsion/initializer/database.rb +4 -4
  40. data/lib/adhearsion/initializer/drb.rb +6 -6
  41. data/lib/adhearsion/initializer/freeswitch.rb +1 -1
  42. data/lib/adhearsion/initializer/ldap.rb +51 -0
  43. data/lib/adhearsion/initializer/rails.rb +8 -8
  44. data/lib/adhearsion/logging.rb +16 -16
  45. data/lib/adhearsion/tasks/deprecations.rb +12 -12
  46. data/lib/adhearsion/tasks/generating.rb +2 -2
  47. data/lib/adhearsion/tasks/testing.rb +7 -7
  48. data/lib/adhearsion/version.rb +1 -1
  49. data/lib/adhearsion/voip/asterisk/agi_server.rb +44 -14
  50. data/lib/adhearsion/voip/asterisk/commands.rb +281 -237
  51. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +8 -8
  52. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +14 -14
  53. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +16 -16
  54. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +39 -39
  55. data/lib/adhearsion/voip/asterisk/config_manager.rb +13 -13
  56. data/lib/adhearsion/voip/asterisk/manager_interface.rb +91 -87
  57. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +739 -739
  58. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +60 -60
  59. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +16 -16
  60. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +1 -1
  61. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +13 -13
  62. data/lib/adhearsion/voip/asterisk/super_manager.rb +3 -3
  63. data/lib/adhearsion/voip/call.rb +101 -64
  64. data/lib/adhearsion/voip/call_routing.rb +9 -9
  65. data/lib/adhearsion/voip/constants.rb +7 -7
  66. data/lib/adhearsion/voip/conveniences.rb +1 -1
  67. data/lib/adhearsion/voip/dial_plan.rb +42 -40
  68. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +27 -27
  69. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +1 -1
  70. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +6 -6
  71. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +17 -17
  72. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +7 -7
  73. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +2 -2
  74. data/lib/adhearsion/voip/dsl/numerical_string.rb +3 -3
  75. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +7 -7
  76. data/lib/adhearsion/voip/freeswitch/event_handler.rb +1 -1
  77. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +20 -20
  78. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +5 -5
  79. data/lib/adhearsion/voip/freeswitch/oes_server.rb +33 -33
  80. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +1 -1
  81. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +2 -2
  82. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +9 -9
  83. data/lib/theatre.rb +18 -18
  84. data/lib/theatre/callback_definition_loader.rb +17 -17
  85. data/lib/theatre/guid.rb +6 -6
  86. data/lib/theatre/invocation.rb +19 -19
  87. data/lib/theatre/namespace_manager.rb +28 -28
  88. metadata +55 -14
@@ -1,21 +1,27 @@
1
1
  require 'adhearsion/voip/asterisk'
2
2
  module Adhearsion
3
3
  class Initializer
4
-
4
+
5
5
  class AsteriskInitializer
6
-
6
+
7
7
  cattr_accessor :config, :agi_server, :ami_client
8
8
  class << self
9
-
9
+
10
10
  def start
11
11
  self.config = AHN_CONFIG.asterisk
12
12
  self.agi_server = initialize_agi
13
13
  self.ami_client = VoIP::Asterisk.manager_interface = initialize_ami if config.ami_enabled?
14
14
  join_server_thread_after_initialized
15
+
16
+ # Make sure we stop everything when we shutdown
17
+ Events.register_callback(:shutdown) do
18
+ ahn_log.info "Shutting down with #{Adhearsion.active_calls.size} active calls"
19
+ self.stop
20
+ end
15
21
  end
16
22
 
17
23
  def stop
18
- agi_server.stop
24
+ agi_server.graceful_shutdown
19
25
  ami_client.disconnect! if ami_client
20
26
  end
21
27
 
@@ -25,7 +31,7 @@ module Adhearsion
25
31
  VoIP::Asterisk::AGI::Server.new :host => config.listening_host,
26
32
  :port => config.listening_port
27
33
  end
28
-
34
+
29
35
  def initialize_ami
30
36
  options = ami_options
31
37
  start_ami_after_initialized
@@ -42,14 +48,14 @@ module Adhearsion
42
48
  end
43
49
  end
44
50
  end
45
-
51
+
46
52
  def ami_options
47
53
  %w(host port username password events).inject({}) do |options, property|
48
54
  options[property.to_sym] = config.ami.send property
49
55
  options
50
56
  end
51
57
  end
52
-
58
+
53
59
  def join_server_thread_after_initialized
54
60
  Events.register_callback(:after_initialized) do
55
61
  begin
@@ -61,7 +67,7 @@ module Adhearsion
61
67
  end
62
68
  IMPORTANT_THREADS << agi_server
63
69
  end
64
-
70
+
65
71
  def start_ami_after_initialized
66
72
  Events.register_callback(:after_initialized) do
67
73
  begin
@@ -76,6 +82,6 @@ module Adhearsion
76
82
 
77
83
  end
78
84
  end
79
-
85
+
80
86
  end
81
87
  end
@@ -21,7 +21,7 @@ module Adhearsion
21
21
  end
22
22
  end
23
23
  extend ConfigurationEntryPoint
24
-
24
+
25
25
  class << self
26
26
  def configure(&block)
27
27
  if Adhearsion.const_defined?(:AHN_CONFIG)
@@ -31,22 +31,22 @@ module Adhearsion
31
31
  end
32
32
  end
33
33
  end
34
-
34
+
35
35
  attr_accessor :automatically_answer_incoming_calls
36
36
  attr_accessor :end_call_on_hangup
37
37
  attr_accessor :end_call_on_error
38
-
38
+
39
39
  def initialize
40
40
  @automatically_answer_incoming_calls = true
41
41
  @end_call_on_hangup = true
42
42
  @end_call_on_error = true
43
43
  yield self if block_given?
44
44
  end
45
-
45
+
46
46
  def ahnrc
47
47
  @ahnrc
48
48
  end
49
-
49
+
50
50
  ##
51
51
  # Load the contents of an .ahnrc file into this Configuration.
52
52
  #
@@ -62,11 +62,11 @@ module Adhearsion
62
62
  @ahnrc = YAML.load(new_ahnrc).freeze
63
63
  end
64
64
  end
65
-
65
+
66
66
  def logging(options)
67
67
  Adhearsion::Logging.logging_level = options[:level]
68
68
  end
69
-
69
+
70
70
  ##
71
71
  # Adhearsion's .ahnrc file is used to define paths to certain parts of the framework. For example, the name dialplan.rb
72
72
  # is actually specified in .ahnrc. This file can actually be just a filename, a filename with a glob (.e.g "*.rb"), an
@@ -89,64 +89,75 @@ module Adhearsion
89
89
  queried_nested_setting = Array queried_nested_setting
90
90
  queried_nested_setting.map { |filename| files_from_glob(filename) }.flatten.uniq
91
91
  end
92
-
92
+
93
93
  private
94
-
94
+
95
95
  def files_from_glob(glob)
96
96
  Dir.glob "#{AHN_ROOT}/#{glob}"
97
97
  end
98
-
98
+
99
99
  class AbstractConfiguration
100
100
  extend ConfigurationEntryPoint
101
-
101
+
102
102
  class << self
103
103
  private
104
104
  def abstract_method!
105
105
  raise "Must be implemented in subclasses"
106
106
  end
107
107
  end
108
-
108
+
109
109
  def initialize(overrides = {})
110
110
  overrides.each_pair do |attribute, value|
111
111
  send("#{attribute}=", value)
112
112
  end
113
113
  end
114
114
  end
115
-
115
+
116
116
  # Abstract superclass for AsteriskConfiguration and FreeSwitchConfiguration.
117
117
  class TelephonyPlatformConfiguration < AbstractConfiguration
118
118
  attr_accessor :listening_port
119
119
  attr_accessor :listening_host
120
-
120
+
121
121
  class << self
122
122
  def default_listening_port
123
123
  abstract_method!
124
124
  end
125
-
125
+
126
126
  def default_listening_host
127
127
  '0.0.0.0'
128
128
  end
129
129
  end
130
-
130
+
131
131
  def initialize(overrides = {})
132
132
  @listening_port = self.class.default_listening_port
133
133
  @listening_host = self.class.default_listening_host
134
134
  super
135
135
  end
136
136
  end
137
-
137
+
138
138
  class AsteriskConfiguration < TelephonyPlatformConfiguration
139
+ attr_accessor :speech_engine
140
+ attr_accessor :argument_delimiter
141
+
139
142
  class << self
140
- attr_accessor :speech_engine
141
-
142
143
  def default_listening_port
143
144
  4573
144
145
  end
146
+
147
+ def default_argument_delimiter
148
+ # Keep Asterisk 1.4 (and prior) as the default to protect upgraders
149
+ '|'
150
+ end
145
151
  end
146
-
152
+
153
+ def initialize(overrides = {})
154
+ @argument_delimiter = self.class.default_argument_delimiter
155
+ super
156
+ end
157
+
147
158
  class AMIConfiguration < AbstractConfiguration
148
159
  attr_accessor :port, :username, :password, :events, :host
149
-
160
+
150
161
  class << self
151
162
  def default_port
152
163
  5038
@@ -155,12 +166,12 @@ module Adhearsion
155
166
  def default_events
156
167
  false
157
168
  end
158
-
169
+
159
170
  def default_host
160
171
  'localhost'
161
172
  end
162
173
  end
163
-
174
+
164
175
  def initialize(overrides = {})
165
176
  self.host = self.class.default_host
166
177
  self.port = self.class.default_port
@@ -171,7 +182,7 @@ module Adhearsion
171
182
  add_configuration_for :AMI
172
183
  end
173
184
  add_configuration_for :Asterisk
174
-
185
+
175
186
  class FreeswitchConfiguration < TelephonyPlatformConfiguration
176
187
  class << self
177
188
  def default_listening_port
@@ -180,7 +191,7 @@ module Adhearsion
180
191
  end
181
192
  end
182
193
  add_configuration_for :Freeswitch
183
-
194
+
184
195
  class DatabaseConfiguration < AbstractConfiguration
185
196
  attr_accessor :connection_options, :orm
186
197
  def initialize(options)
@@ -189,7 +200,15 @@ module Adhearsion
189
200
  end
190
201
  end
191
202
  add_configuration_for :Database
192
-
203
+
204
+ class LdapConfiguration < AbstractConfiguration
205
+ attr_accessor :connection_options
206
+ def initialize(options)
207
+ @connection_options = options
208
+ end
209
+ end
210
+ add_configuration_for :Ldap
211
+
193
212
  class DrbConfiguration < AbstractConfiguration
194
213
  attr_accessor :port
195
214
  attr_accessor :host
@@ -201,17 +220,17 @@ module Adhearsion
201
220
  def default_port
202
221
  9050
203
222
  end
204
-
223
+
205
224
  def default_host
206
225
  'localhost'
207
226
  end
208
227
  end
209
-
228
+
210
229
  def initialize(overrides = {})
211
230
  self.port = overrides[:port] || self.class.default_port
212
231
  self.host = overrides[:host] || self.class.default_host
213
232
  self.acl = overrides[:raw_acl]
214
-
233
+
215
234
  unless acl
216
235
  self.acl = []
217
236
  overrides[ :deny].to_a.each { |ip| acl << 'deny' << ip }
@@ -221,22 +240,18 @@ module Adhearsion
221
240
  end
222
241
  end
223
242
  add_configuration_for :Drb
224
-
243
+
225
244
  class RailsConfiguration < AbstractConfiguration
226
-
227
- SUPPORTED_RAILS_ENVIRONMENTS = [:development, :test, :production]
228
-
245
+
229
246
  attr_accessor :rails_root, :environment
230
247
  def initialize(options)
231
248
  path_to_rails, environment = check_options options
232
249
  @rails_root = File.expand_path(path_to_rails)
233
250
  @environment = environment.to_sym
234
- raise ArgumentError, "Unrecognized environment type #@environment. Supported: " +
235
- SUPPORTED_RAILS_ENVIRONMENTS.to_sentence unless SUPPORTED_RAILS_ENVIRONMENTS.include?(@environment)
236
251
  end
237
-
252
+
238
253
  private
239
-
254
+
240
255
  def check_options(options)
241
256
  options = options.clone
242
257
  path = options.delete :path
@@ -246,9 +261,9 @@ module Adhearsion
246
261
  raise ArgumentError, "Must supply an :path argument to the Rails initializer!" unless path
247
262
  [path, env]
248
263
  end
249
-
264
+
250
265
  end
251
266
  add_configuration_for :Rails
252
-
267
+
253
268
  end
254
269
  end
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Adhearsion
4
4
  class Initializer
5
-
5
+
6
6
  class DatabaseInitializer
7
-
7
+
8
8
  class << self
9
9
 
10
10
  def start
@@ -38,13 +38,13 @@ module Adhearsion
38
38
  load model
39
39
  end
40
40
  end
41
-
41
+
42
42
  def establish_connection
43
43
  ActiveRecord::Base.establish_connection @@config.connection_options
44
44
  end
45
45
 
46
46
  end
47
47
  end
48
-
48
+
49
49
  end
50
50
  end
@@ -8,23 +8,23 @@ module Adhearsion
8
8
  class DrbInitializer
9
9
 
10
10
  class << self
11
-
11
+
12
12
  def start
13
13
  config = Adhearsion::AHN_CONFIG.drb
14
14
  DRb.install_acl ACL.new(config.acl) if config.acl
15
-
15
+
16
16
  drb_door = Object.new
17
17
  Components.component_manager.extend_object_with(drb_door, :rpc)
18
-
18
+
19
19
  DRb.start_service "druby://#{config.host}:#{config.port}", drb_door
20
-
20
+
21
21
  ahn_log "Starting DRb on #{config.host}:#{config.port}"
22
22
  end
23
-
23
+
24
24
  def stop
25
25
  DRb.stop_service
26
26
  end
27
-
27
+
28
28
  end
29
29
  end
30
30
  end
@@ -6,7 +6,7 @@ require "adhearsion/voip/freeswitch/inbound_connection_manager"
6
6
  require "adhearsion/voip/dsl/dialplan/control_passing_exception"
7
7
 
8
8
  oes_enabled = Adhearsion::Configuration.core.voip.freeswitch.oes && Adhearsion::Configuration.core.voip.freeswitch.oes.port
9
-
9
+
10
10
 
11
11
  if oes_enabled
12
12
 
@@ -0,0 +1,51 @@
1
+ # TODO: Have all of the initializer modules required and then traverse the subclasses, asking them if they're enabled. If they are enabled, then they should do their initialization stuff. Is this really necessary to develop this entirely new system when the components system exists?
2
+
3
+ module Adhearsion
4
+ class Initializer
5
+
6
+ class LdapInitializer
7
+
8
+ class << self
9
+
10
+ def start
11
+ require_dependencies
12
+ require_models
13
+ @@config = Adhearsion::AHN_CONFIG.ldap
14
+ # You may need to uncomment the following line for older versions of ActiveRecord
15
+ # ActiveRecord::Base.allow_concurrency = true
16
+ establish_connection
17
+ end
18
+
19
+ def stop
20
+ ActiveLdap::Base.remove_connection
21
+ end
22
+
23
+ private
24
+
25
+ # TODO: It appears that ActiveLdap does not have a connection validation
26
+ # or reconnection routine.
27
+ #def create_call_hook_for_connection_cleanup
28
+ # Events.register_callback([:asterisk, :before_call]) do
29
+ # ActiveLdap::Base.verify_active_connections!
30
+ # end
31
+ #end
32
+
33
+ def require_dependencies
34
+ require 'active_ldap'
35
+ end
36
+
37
+ def require_models
38
+ AHN_CONFIG.files_from_setting("paths", "models").each do |model|
39
+ load model
40
+ end
41
+ end
42
+
43
+ def establish_connection
44
+ ActiveLdap::Base.setup_connection @@config.connection_options
45
+ end
46
+
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -1,16 +1,16 @@
1
1
  require 'adhearsion/voip/asterisk'
2
2
 
3
3
  module Adhearsion
4
- class Initializer
4
+ class Initializer
5
5
  class RailsInitializer
6
-
6
+
7
7
  cattr_accessor :rails_root, :config, :environment
8
8
  class << self
9
-
9
+
10
10
  def start
11
11
  ahn_config = Adhearsion::AHN_CONFIG
12
12
  self.config = ahn_config.rails
13
- self.rails_root = config.rails_root
13
+ self.rails_root = config.rails_root
14
14
  self.environment = config.environment
15
15
  raise "You cannot enable the database and Rails at the same time!" if ahn_config.database_enabled?
16
16
  raise "Error loading Rails environment in #{rails_root.inspect}. " +
@@ -24,18 +24,18 @@ module Adhearsion
24
24
  end
25
25
  end
26
26
  end
27
-
27
+
28
28
  private
29
-
29
+
30
30
  def load_rails
31
31
  environment_file = File.expand_path(rails_root + "/config/environment.rb")
32
32
  raise "There is no config/environment.rb file!" unless File.exists?(environment_file)
33
33
  ENV['RAILS_ENV'] = environment.to_s
34
34
  require environment_file
35
35
  end
36
-
36
+
37
37
  end
38
-
38
+
39
39
  end
40
40
  end
41
41
  end