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
@@ -2,16 +2,16 @@ module Adhearsion
2
2
  module VoIP
3
3
  module Asterisk
4
4
  module Manager
5
-
5
+
6
6
  ##
7
7
  # Higher level abstraction of the Asterisk Manager Interface.
8
8
  #
9
9
  class SuperManager
10
-
10
+
11
11
  def initialize
12
12
  raise NotImplementedError
13
13
  end
14
-
14
+
15
15
  end
16
16
  end
17
17
  end
@@ -5,21 +5,21 @@ module Adhearsion
5
5
  def active_calls
6
6
  @calls ||= Calls.new
7
7
  end
8
-
8
+
9
9
  def receive_call_from(io, &block)
10
10
  active_calls << (call = Call.receive_from(io, &block))
11
11
  call
12
12
  end
13
-
13
+
14
14
  def remove_inactive_call(call)
15
15
  active_calls.remove_inactive_call(call)
16
16
  end
17
17
  end
18
-
18
+
19
19
  class Hangup < Exception
20
20
  # At the moment, we'll just use this to end a call-handling Thread.
21
21
  end
22
-
22
+
23
23
  ##
24
24
  # This manages the list of calls the Adhearsion service receives
25
25
  class Calls
@@ -27,44 +27,44 @@ module Adhearsion
27
27
  @semaphore = Monitor.new
28
28
  @calls = {}
29
29
  end
30
-
30
+
31
31
  def <<(call)
32
32
  atomically do
33
33
  calls[call.unique_identifier] = call
34
34
  end
35
35
  end
36
-
36
+
37
37
  def any?
38
38
  atomically do
39
39
  !calls.empty?
40
40
  end
41
41
  end
42
-
42
+
43
43
  def size
44
44
  atomically do
45
45
  calls.size
46
46
  end
47
47
  end
48
-
48
+
49
49
  def remove_inactive_call(call)
50
50
  atomically do
51
51
  calls.delete call.unique_identifier
52
52
  end
53
53
  end
54
-
54
+
55
55
  # Searches all active calls by their unique_identifier. See Call#unique_identifier.
56
56
  def find(id)
57
57
  atomically do
58
58
  return calls[id]
59
59
  end
60
60
  end
61
-
61
+
62
62
  def clear!
63
63
  atomically do
64
64
  calls.clear
65
65
  end
66
66
  end
67
-
67
+
68
68
  def with_tag(tag)
69
69
  atomically do
70
70
  calls.inject(Array.new) do |calls_with_tag,(key,call)|
@@ -72,22 +72,22 @@ module Adhearsion
72
72
  end
73
73
  end
74
74
  end
75
-
75
+
76
76
  def to_a
77
77
  calls.values
78
78
  end
79
-
79
+
80
80
  private
81
81
  attr_reader :semaphore, :calls
82
-
82
+
83
83
  def atomically(&block)
84
84
  semaphore.synchronize(&block)
85
85
  end
86
-
86
+
87
87
  end
88
-
88
+
89
89
  class UselessCallException < Exception; end
90
-
90
+
91
91
  class MetaAgiCallException < Exception
92
92
  attr_reader :call
93
93
  def initialize(call)
@@ -95,17 +95,50 @@ module Adhearsion
95
95
  @call = call
96
96
  end
97
97
  end
98
-
98
+
99
99
  class FailedExtensionCallException < MetaAgiCallException; end
100
-
100
+
101
101
  class HungupExtensionCallException < MetaAgiCallException; end
102
-
102
+
103
103
  ##
104
104
  # Encapsulates call-related data and behavior.
105
105
  # For example, variables passed in on call initiation are
106
- # accessible here as attributes
106
+ # accessible here as attributes
107
107
  class Call
108
-
108
+
109
+ ##
110
+ # Wraps the Queue object (subclasses it) so we can handle runaway threads,
111
+ # namely those originating from using with_next_message in commands.rb - this
112
+ # overrides << to check for the :cancel symbol and trigger the automessaging_tainted
113
+ # instance variable.
114
+ class CallMessageQueue < Queue
115
+
116
+ class InboxClosedException < Exception
117
+ # this gets raised when the :cancel message is delivered to the queue and with_next_message (or similar auto-message-iteration)
118
+ # features are called.
119
+ end
120
+
121
+ attr_reader :open
122
+
123
+ def initialize
124
+ @open = true
125
+ super
126
+ end
127
+
128
+ def <<(queue_obj)
129
+ @open = false if queue_obj == :cancel
130
+ super(queue_obj)
131
+ end
132
+
133
+ def pop
134
+ raise Adhearsion::Call::CallMessageQueue::InboxClosedException, "The message queue for this call has aleady been disabled." if !@open
135
+ super
136
+ end
137
+
138
+
139
+ end
140
+
141
+
109
142
  # This is basically a translation of ast_channel_reason2str() from main/channel.c and
110
143
  # ast_control_frame_type in include/asterisk/frame.h in the Asterisk source code. When
111
144
  # Asterisk jumps to the 'failed' extension, it sets a REASON channel variable to a number.
@@ -131,8 +164,8 @@ module Adhearsion
131
164
  :unhold, # Indicate call is left from hold
132
165
  :vidupdate # Indicate video frame update
133
166
  ]
134
-
135
-
167
+
168
+
136
169
  class << self
137
170
  ##
138
171
  # The primary public interface for creating a Call instance.
@@ -143,14 +176,14 @@ module Adhearsion
143
176
  block.call(call) if block
144
177
  end
145
178
  end
146
-
179
+
147
180
  private
148
181
  def variable_parser_for(io)
149
182
  Variables::Parser.parse(io)
150
183
  end
151
-
184
+
152
185
  end
153
-
186
+
154
187
  attr_accessor :io, :type, :variables, :originating_voip_platform, :inbox
155
188
  def initialize(io, variables)
156
189
  @io, @variables = io, variables.symbolize_keys
@@ -173,13 +206,13 @@ module Adhearsion
173
206
  @tags << symbol
174
207
  end
175
208
  end
176
-
209
+
177
210
  def remove_tag(symbol)
178
211
  @tag_mutex.synchronize do
179
212
  @tags.reject! { |tag| tag == symbol }
180
213
  end
181
214
  end
182
-
215
+
183
216
  def tagged_with?(symbol)
184
217
  @tag_mutex.synchronize do
185
218
  @tags.include? symbol
@@ -191,8 +224,12 @@ module Adhearsion
191
224
  end
192
225
  alias << deliver_message
193
226
 
227
+ def can_use_messaging?
228
+ return inbox.open == true
229
+ end
230
+
194
231
  def inbox
195
- @inbox ||= Queue.new
232
+ @inbox ||= CallMessageQueue.new
196
233
  end
197
234
 
198
235
  def hangup!
@@ -203,18 +240,18 @@ module Adhearsion
203
240
  def closed?
204
241
  io.closed?
205
242
  end
206
-
243
+
207
244
  # Asterisk sometimes uses the "failed" extension to indicate a failed dial attempt.
208
245
  # Since it may be important to handle these, this flag helps the dialplan Manager
209
246
  # figure that out.
210
247
  def failed_call?
211
248
  @failed_call
212
249
  end
213
-
250
+
214
251
  def hungup_call?
215
252
  @hungup_call
216
253
  end
217
-
254
+
218
255
  # Adhearsion indexes calls by this identifier so they may later be found and manipulated. For calls from Asterisk, this
219
256
  # method uses the following properties for uniqueness, falling back to the next if one is for some reason unavailable:
220
257
  #
@@ -230,13 +267,13 @@ module Adhearsion
230
267
  raise NotImplementedError
231
268
  end
232
269
  end
233
-
270
+
234
271
  def define_variable_accessors(recipient=self)
235
- variables.each do |key, value|
272
+ variables.each do |key, value|
236
273
  define_singleton_accessor_with_pair(key, value, recipient)
237
274
  end
238
275
  end
239
-
276
+
240
277
  def extract_failed_reason_from(environment)
241
278
  if originating_voip_platform == :asterisk
242
279
  failed_reason = environment.variable 'REASON'
@@ -244,30 +281,30 @@ module Adhearsion
244
281
  define_singleton_accessor_with_pair(:failed_reason, failed_reason, environment)
245
282
  end
246
283
  end
247
-
284
+
248
285
  private
249
-
286
+
250
287
  def define_singleton_accessor_with_pair(key, value, recipient=self)
251
288
  recipient.metaclass.send :attr_accessor, key unless recipient.class.respond_to?("#{key}=")
252
289
  recipient.send "#{key}=", value
253
290
  end
254
-
291
+
255
292
  def check_if_valid_call
256
293
  extension = variables[:extension]
257
294
  @failed_call = true if extension == 'failed'
258
295
  @hungup_call = true if extension == 'h'
259
296
  raise UselessCallException if extension == 't' # TODO: Move this whole method to Manager
260
297
  end
261
-
298
+
262
299
  def set_originating_voip_platform!
263
300
  # TODO: we can make this determination programatically at some point,
264
301
  # but it will probably involve a bit more engineering than just a case statement (like
265
302
  # subclasses of Call for the various platforms), so we'll be totally cheap for now.
266
303
  self.originating_voip_platform = :asterisk
267
304
  end
268
-
305
+
269
306
  module Variables
270
-
307
+
271
308
  module Coercions
272
309
 
273
310
  COERCION_ORDER = %w{
@@ -285,7 +322,7 @@ module Adhearsion
285
322
  }
286
323
 
287
324
  class << self
288
-
325
+
289
326
  def remove_agi_prefixes_from_keys_and_strip_whitespace(variables)
290
327
  variables.inject({}) do |new_variables,(key,value)|
291
328
  returning new_variables do
@@ -294,7 +331,7 @@ module Adhearsion
294
331
  end
295
332
  end
296
333
  end
297
-
334
+
298
335
  def coerce_keys_into_symbols(variables)
299
336
  variables.inject({}) do |new_variables,(key,value)|
300
337
  returning new_variables do
@@ -302,13 +339,13 @@ module Adhearsion
302
339
  end
303
340
  end
304
341
  end
305
-
342
+
306
343
  def coerce_extension_into_phone_number_object(variables)
307
344
  returning variables do
308
345
  variables[:extension] = Adhearsion::VoIP::DSL::PhoneNumber.new(variables[:extension])
309
346
  end
310
347
  end
311
-
348
+
312
349
  def coerce_numerical_values_to_numerics(variables)
313
350
  variables.inject({}) do |vars,(key,value)|
314
351
  returning vars do
@@ -344,19 +381,19 @@ module Adhearsion
344
381
  def replace_yes_no_answers_with_booleans(variables)
345
382
  variables.each do |key,value|
346
383
  case value
347
- when 'yes' : variables[key] = true
348
- when 'no' : variables[key] = false
384
+ when 'yes' then variables[key] = true
385
+ when 'no' then variables[key] = false
349
386
  end
350
387
  end
351
388
  end
352
-
389
+
353
390
  def coerce_request_into_uri_object(variables)
354
391
  if variables[:request]
355
392
  variables[:request] = URI.parse(variables[:request]) unless variables[:request].kind_of? URI
356
393
  end
357
394
  variables
358
395
  end
359
-
396
+
360
397
  def coerce_type_of_number_into_symbol(variables)
361
398
  returning variables do
362
399
  variables[:type_of_calling_number] = Adhearsion::VoIP::Constants::Q931_TYPE_OF_NUMBER[variables.delete(:callington).to_i]
@@ -376,7 +413,7 @@ module Adhearsion
376
413
  end
377
414
  end
378
415
  end
379
-
416
+
380
417
  def override_variables_with_query_params(variables)
381
418
  returning variables do
382
419
  if variables[:query]
@@ -386,50 +423,50 @@ module Adhearsion
386
423
  end
387
424
  end
388
425
  end
389
-
426
+
390
427
  def remove_dashes_from_context_name(variables)
391
428
  returning variables do
392
429
  variables[:context].gsub!('-', '_')
393
430
  end
394
431
  end
395
-
432
+
396
433
  end
397
434
  end
398
435
 
399
436
  class Parser
400
-
437
+
401
438
  class << self
402
439
  def parse(*args, &block)
403
440
  returning new(*args, &block) do |parser|
404
441
  parser.parse
405
442
  end
406
443
  end
407
-
444
+
408
445
  def coerce_variables(variables)
409
446
  Coercions::COERCION_ORDER.inject(variables) do |tmp_variables, coercing_method_name|
410
447
  Coercions.send(coercing_method_name, tmp_variables)
411
448
  end
412
449
  end
413
-
450
+
414
451
  def separate_line_into_key_value_pair(line)
415
452
  line.match(/^([^:]+):\s?(.+)/).captures
416
453
  end
417
454
  end
418
-
455
+
419
456
  attr_reader :io, :variables, :lines
420
457
  def initialize(io)
421
458
  @io = io
422
459
  @lines = []
423
460
  end
424
-
461
+
425
462
  def parse
426
463
  extract_variable_lines_from_io
427
464
  initialize_variables_as_hash_from_lines
428
465
  @variables = self.class.coerce_variables(variables)
429
466
  end
430
-
467
+
431
468
  private
432
-
469
+
433
470
  def initialize_variables_as_hash_from_lines
434
471
  @variables = lines.inject({}) do |new_variables,line|
435
472
  returning new_variables do
@@ -438,16 +475,16 @@ module Adhearsion
438
475
  end
439
476
  end
440
477
  end
441
-
478
+
442
479
  def extract_variable_lines_from_io
443
480
  while line = io.readline.chomp
444
481
  break if line.empty?
445
482
  @lines << line
446
483
  end
447
484
  end
448
-
485
+
449
486
  end
450
-
487
+
451
488
  end
452
- end
489
+ end
453
490
  end