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
@@ -3,7 +3,7 @@ module Adhearsion
3
3
  module VoIP
4
4
  module Asterisk
5
5
  class ConfigurationManager
6
-
6
+
7
7
  class << self
8
8
  def normalize_configuration(file_contents)
9
9
  # cat sip.conf | sed -e 's/\s*;.*$//g' | sed -e '/^;.*$/d' | sed -e '/^\s*$/d'
@@ -12,39 +12,39 @@ module Adhearsion
12
12
  end.join("\n").squeeze("\n")
13
13
  end
14
14
  end
15
-
15
+
16
16
  attr_reader :filename
17
-
17
+
18
18
  def initialize(filename)
19
19
  @filename = filename
20
20
  end
21
-
21
+
22
22
  def sections
23
23
  @sections ||= read_configuration
24
24
  end
25
-
25
+
26
26
  def [](section_name)
27
27
  result = sections.find { |(name, *rest)| section_name == name }
28
28
  result.last if result
29
29
  end
30
-
30
+
31
31
  def delete_section(section_name)
32
32
  sections.reject! { |(name, *rest)| section_name == name }
33
33
  end
34
-
34
+
35
35
  def new_section(name, properties={})
36
36
  sections << [name, properties]
37
37
  end
38
-
38
+
39
39
  private
40
-
40
+
41
41
  def read_configuration
42
42
  normalized_file = self.class.normalize_configuration execute(read_command)
43
43
  normalized_file.split(/^\[([-_\w]+)\]$/)[1..-1].enum_slice(2).map do |(name,properties)|
44
44
  [name, hash_from_properties(properties)]
45
45
  end
46
46
  end
47
-
47
+
48
48
  def hash_from_properties(properties)
49
49
  properties.split(/\n+/).inject({}) do |property_hash,property|
50
50
  all, name, value = *property.match(/^\s*([^=]+?)\s*=\s*(.+)\s*$/)
@@ -53,15 +53,15 @@ module Adhearsion
53
53
  property_hash
54
54
  end
55
55
  end
56
-
56
+
57
57
  def execute(command)
58
58
  %x[command]
59
59
  end
60
-
60
+
61
61
  def read_command
62
62
  "cat #{filename}"
63
63
  end
64
-
64
+
65
65
  end
66
66
  end
67
67
  end
@@ -3,7 +3,7 @@ require 'adhearsion/voip/asterisk/manager_interface/ami_lexer'
3
3
  module Adhearsion
4
4
  module VoIP
5
5
  module Asterisk
6
-
6
+
7
7
  ##
8
8
  # Sorry, this AMI class has been deprecated. Please see http://docs.adhearsion.com/Asterisk_Manager_Interface for
9
9
  # documentation on the new way of handling AMI. This new version is much better and should not require an enormous
@@ -11,14 +11,14 @@ module Adhearsion
11
11
  #
12
12
  class AMI
13
13
  def initialize
14
- raise "Sorry, this AMI class has been deprecated. Please see http://docs.adhearsion.com/Asterisk_Manager_Interface for documentation on the new way of handling AMI. This new version is much better and should not require an enormous migration on your part."
14
+ raise "Sorry, this AMI class has been deprecated. Please see http://docs.adhearsion.com/display/adhearsion/Asterisk+Manager+Interface for documentation on the new way of handling AMI. This new version is much better and should not require an enormous migration on your part."
15
15
  end
16
16
  end
17
-
17
+
18
18
  mattr_accessor :manager_interface
19
-
19
+
20
20
  module Manager
21
-
21
+
22
22
  ##
23
23
  # This class abstracts a connection to the Asterisk Manager Interface. Its purpose is, first and foremost, to make
24
24
  # the protocol consistent. Though the classes employed to assist this class (ManagerInterfaceAction,
@@ -28,17 +28,17 @@ module Adhearsion
28
28
  # For a higher-level abstraction of the Asterisk Manager Interface, see the SuperManager class.
29
29
  #
30
30
  class ManagerInterface
31
-
31
+
32
32
  CAUSAL_EVENT_NAMES = ["queuestatus", "sippeers", "parkedcalls", "status", "dahdishowchannels"] unless defined? CAUSAL_EVENT_NAMES
33
-
33
+
34
34
  class << self
35
-
35
+
36
36
  def connect(*args)
37
37
  returning new(*args) do |connection|
38
38
  connection.connect!
39
39
  end
40
40
  end
41
-
41
+
42
42
  def replies_with_action_id?(name, headers={})
43
43
  name = name.to_s.downcase
44
44
  # TODO: Expand this case statement
@@ -47,15 +47,15 @@ module Adhearsion
47
47
  false
48
48
  else
49
49
  true
50
- end
50
+ end
51
51
  end
52
-
52
+
53
53
  ##
54
54
  # When sending an action with "causal events" (i.e. events which must be collected to form a proper
55
55
  # response), AMI should send a particular event which instructs us that no more events will be sent.
56
56
  # This event is called the "causal event terminator".
57
57
  #
58
- # Note: you must supply both the name of the event and any headers because it's possible that some uses of an
58
+ # Note: you must supply both the name of the event and any headers because it's possible that some uses of an
59
59
  # action (i.e. same name, different headers) have causal events while other uses don't.
60
60
  #
61
61
  # @param [String] name the name of the event
@@ -65,16 +65,16 @@ module Adhearsion
65
65
  def has_causal_events?(name, headers={})
66
66
  CAUSAL_EVENT_NAMES.include? name.to_s.downcase
67
67
  end
68
-
68
+
69
69
  ##
70
70
  # Used to determine the event name for an action which has causal events.
71
- #
71
+ #
72
72
  # @param [String] action_name
73
73
  # @return [String] The corresponding event name which signals the completion of the causal event sequence.
74
- #
74
+ #
75
75
  def causal_event_terminator_name_for(action_name)
76
76
  return nil unless has_causal_events?(action_name)
77
- action_name = action_name.to_s.downcase
77
+ action_name = action_name.to_s.downcase
78
78
  case action_name
79
79
  when "queuestatus", 'parkedcalls', "status"
80
80
  action_name + "complete"
@@ -82,9 +82,9 @@ module Adhearsion
82
82
  "peerlistcomplete"
83
83
  end
84
84
  end
85
-
85
+
86
86
  end
87
-
87
+
88
88
  DEFAULT_SETTINGS = {
89
89
  :host => "localhost",
90
90
  :port => 5038,
@@ -92,9 +92,9 @@ module Adhearsion
92
92
  :password => "secret",
93
93
  :events => true
94
94
  }.freeze unless defined? DEFAULT_SETTINGS
95
-
95
+
96
96
  attr_reader *DEFAULT_SETTINGS.keys
97
-
97
+
98
98
  ##
99
99
  # Creates a new Asterisk Manager Interface connection and exposes certain methods to control it. The constructor
100
100
  # takes named parameters as Symbols. Note: if the :events option is given, this library will establish a separate
@@ -105,46 +105,46 @@ module Adhearsion
105
105
  #
106
106
  def initialize(options={})
107
107
  options = parse_options options
108
-
108
+
109
109
  @host = options[:host]
110
- @username = options[:username]
110
+ @username = options[:username]
111
111
  @password = options[:password]
112
112
  @port = options[:port]
113
113
  @events = options[:events]
114
-
114
+
115
115
  @sent_messages = {}
116
116
  @sent_messages_lock = Mutex.new
117
-
117
+
118
118
  @actions_lexer = DelegatingAsteriskManagerInterfaceLexer.new self, \
119
119
  :message_received => :action_message_received,
120
120
  :error_received => :action_error_received
121
-
121
+
122
122
  @write_queue = Queue.new
123
-
123
+
124
124
  if @events
125
125
  @events_lexer = DelegatingAsteriskManagerInterfaceLexer.new self, \
126
126
  :message_received => :event_message_received,
127
- :error_received => :event_error_received
127
+ :error_received => :event_error_received
128
128
  end
129
129
  end
130
-
130
+
131
131
  def action_message_received(message)
132
132
  if message.kind_of? Manager::ManagerInterfaceEvent
133
133
  # Trigger the return value of the waiting action id...
134
134
  corresponding_action = @current_action_with_causal_events
135
135
  event_collection = @event_collection_for_current_action
136
-
136
+
137
137
  if corresponding_action
138
-
138
+
139
139
  # If this is the meta-event which signals no more events will follow and the response is complete.
140
140
  if message.name.downcase == corresponding_action.causal_event_terminator_name
141
-
141
+
142
142
  # Result found! Wake up any Threads waiting
143
143
  corresponding_action.future_resource.resource = event_collection.freeze
144
-
144
+
145
145
  @current_action_with_causal_events = nil
146
146
  @event_collection_for_current_action = nil
147
-
147
+
148
148
  else
149
149
  event_collection << message
150
150
  # We have more causal events coming.
@@ -152,7 +152,7 @@ module Adhearsion
152
152
  else
153
153
  ahn_log.ami.error "Got an unexpected event on actions socket! This may be a bug! #{message.inspect}"
154
154
  end
155
-
155
+
156
156
  elsif message["ActionID"].nil?
157
157
  # No ActionID! Release the write lock and wake up the waiter
158
158
  else
@@ -160,7 +160,7 @@ module Adhearsion
160
160
  corresponding_action = data_for_message_received_with_action_id action_id
161
161
  if corresponding_action
162
162
  message.action = corresponding_action
163
-
163
+
164
164
  if corresponding_action.has_causal_events?
165
165
  # By this point the write loop will already have started blocking by calling the response() method on the
166
166
  # action. Because we must collect more events before we wake the write loop up again, let's create these
@@ -176,10 +176,10 @@ module Adhearsion
176
176
  end
177
177
  end
178
178
  end
179
-
179
+
180
180
  def action_error_received(ami_error)
181
181
  action_id = ami_error["ActionID"]
182
-
182
+
183
183
  corresponding_action = data_for_message_received_with_action_id action_id
184
184
 
185
185
  if corresponding_action
@@ -188,7 +188,7 @@ module Adhearsion
188
188
  ahn_log.ami.error "Received an AMI error with an unrecognized ActionID!! This may be an bug! #{ami_error.inspect}"
189
189
  end
190
190
  end
191
-
191
+
192
192
  ##
193
193
  # Called only when this ManagerInterface is instantiated with events enabled.
194
194
  #
@@ -197,22 +197,22 @@ module Adhearsion
197
197
  # TODO: convert the event name to a certain namespace.
198
198
  Events.trigger %w[asterisk manager_interface], event
199
199
  end
200
-
200
+
201
201
  def event_error_received(message)
202
202
  # Does this ever even occur?
203
203
  ahn_log.ami.error "Hmmm, got an error on the AMI events-only socket! This must be a bug! #{message.inspect}"
204
204
  end
205
-
205
+
206
206
  ##
207
207
  # Called when our Ragel parser encounters some unexpected syntax from Asterisk. Anytime this is called, it should
208
208
  # be considered a bug in Adhearsion. Note: this same method is called regardless of whether the syntax error
209
209
  # happened on the actions socket or on the events socket.
210
210
  #
211
211
  def syntax_error_encountered(ignored_chunk)
212
- ahn_log.ami.error "ADHEARSION'S AMI PARSER ENCOUNTERED A SYNTAX ERROR! " +
212
+ ahn_log.ami.error "ADHEARSION'S AMI PARSER ENCOUNTERED A SYNTAX ERROR! " +
213
213
  "PLEASE REPORT THIS ON http://bugs.adhearsion.com! OFFENDING TEXT:\n#{ignored_chunk.inspect}"
214
214
  end
215
-
215
+
216
216
  ##
217
217
  # Must be called after instantiation. Also see ManagerInterface::connect().
218
218
  #
@@ -223,35 +223,39 @@ module Adhearsion
223
223
  establish_events_connection if @events
224
224
  self
225
225
  end
226
-
226
+
227
227
  def actions_connection_established
228
228
  @actions_state = :connected
229
229
  @actions_writer_thread = Thread.new(&method(:write_loop))
230
230
  end
231
-
231
+
232
232
  def actions_connection_disconnected
233
233
  @actions_state = :disconnected
234
+ ahn_log.ami.error "AMI connection for ACTION disconnected !!!"
235
+ establish_actions_connection
234
236
  end
235
-
237
+
236
238
  def events_connection_established
237
239
  @events_state = :connected
238
240
  end
239
-
240
- def actions_connection_disconnected
241
+
242
+ def events_connection_disconnected
241
243
  @events_state = :disconnected
244
+ ahn_log.ami.error "AMI connection for EVENT disconnected !!!"
245
+ establish_events_connection
242
246
  end
243
-
247
+
244
248
  def disconnect!
245
249
  # PSEUDO CODE
246
250
  # TODO: Go through all the waiting condition variables and raise an exception
247
251
  #@write_queue << :STOP!
248
- raise NotImplementedError
252
+ #raise NotImplementedError
249
253
  end
250
-
254
+
251
255
  def dynamic
252
256
  # TODO: Return an object which responds to method_missing
253
257
  end
254
-
258
+
255
259
  ##
256
260
  # Used to directly send a new action to Asterisk. Note: NEVER supply an ActionID; these are handled internally.
257
261
  #
@@ -269,7 +273,7 @@ module Adhearsion
269
273
  raise NotImplementedError
270
274
  end
271
275
  end
272
-
276
+
273
277
  ##
274
278
  # Sends an action over the AMI connection and blocks your Thread until the response comes in. If there was an error
275
279
  # for some reason, the error will be raised as an ManagerInterfaceError.
@@ -284,16 +288,16 @@ module Adhearsion
284
288
  raise response if response.kind_of?(ManagerInterfaceError)
285
289
  end
286
290
  end
287
-
291
+
288
292
  alias send_action send_action_synchronously
289
-
290
-
293
+
294
+
291
295
  ####### #######
292
296
  ########### ###########
293
- ################# SOON-DEPRECATED COMMANDS #################
297
+ ################# SOON-DEPRECATED COMMANDS #################
294
298
  ########### ###########
295
299
  ####### #######
296
-
300
+
297
301
  # ping sends an action to the Asterisk Manager Interface that returns a pong
298
302
  # more details here: http://www.voip-info.org/wiki/index.php?page=Asterisk+Manager+API+Action+Ping
299
303
  def ping
@@ -301,14 +305,14 @@ module Adhearsion
301
305
  send_action "Ping"
302
306
  true
303
307
  end
304
-
308
+
305
309
  def deprecation_warning
306
310
  ahn_log.ami.deprecation.warn "The implementation of the ping, originate, introduce, hangup, call_into_context " +
307
311
  "and call_and_exec methods will soon be moved from this class to SuperManager. At the moment, the " +
308
312
  "SuperManager abstractions are not completed. Don't worry. The migration to SuperManager will be very easy."+
309
313
  " See http://docs.adhearsion.com/AMI for more information."
310
314
  end
311
-
315
+
312
316
  # The originate method launches a call to Asterisk, full details here:
313
317
  # http://www.voip-info.org/tiki-index.php?page=Asterisk+Manager+API+Action+Originate
314
318
  # Takes these arguments as a hash:
@@ -324,7 +328,7 @@ module Adhearsion
324
328
  # Application: Application to use on connect (use Data for parameters)
325
329
  # Data : Data if Application parameter is used
326
330
  # Async: For the origination to be asynchronous (allows multiple calls to be generated without waiting for a response)
327
- # ActionID: The request identifier. It allows you to identify the response to this request.
331
+ # ActionID: The request identifier. It allows you to identify the response to this request.
328
332
  # You may use a number or a string. Useful when you make several simultaneous requests.
329
333
  #
330
334
  # For example:
@@ -375,7 +379,7 @@ module Adhearsion
375
379
  originate args
376
380
  end
377
381
 
378
- # call_into_context is syntactic sugar for the Asterisk originate command that allows you to
382
+ # call_into_context is syntactic sugar for the Asterisk originate command that allows you to
379
383
  # lanuch a call into a particular context. For example:
380
384
  #
381
385
  # call_into_context('SIP/1000@sipnetworks.com', 'my_context', { :variables => { :session_guid => new_guid }})
@@ -386,20 +390,20 @@ module Adhearsion
386
390
  args[:exten] = options[:extension] if options[:extension]
387
391
  args[:caller_id] = options[:caller_id] if options[:caller_id]
388
392
  if options[:variables] && options[:variables].kind_of?(Hash)
389
- args[:variable] = options[:variables].map {|pair| pair.join('=')}.join('|')
393
+ args[:variable] = options[:variables].map {|pair| pair.join('=')}.join(AHN_CONFIG.asterisk.argument_delimiter)
390
394
  end
391
395
  originate args
392
396
  end
393
-
397
+
394
398
  ####### #######
395
399
  ########### ###########
396
- ################# END SOON-DEPRECATED COMMANDS #################
400
+ ################# END SOON-DEPRECATED COMMANDS #################
397
401
  ########### ###########
398
402
  ####### #######
399
403
 
400
-
404
+
401
405
  protected
402
-
406
+
403
407
  ##
404
408
  # This class will be removed once this AMI library fully supports all known protocol anomalies.
405
409
  #
@@ -411,21 +415,21 @@ module Adhearsion
411
415
  def initialize(name)
412
416
  super "At the moment this AMI library doesn't support the #{name.inspect} action because it causes a protocol anomaly. Support for it will be coming shortly."
413
417
  end
414
-
418
+
415
419
  end
416
-
420
+
417
421
  def check_action_name(name)
418
422
  name = name.to_s.downcase
419
423
  raise UnsupportedActionName.new(name) if UnsupportedActionName::UNSUPPORTED_ACTION_NAMES.include? name
420
424
  true
421
425
  end
422
-
426
+
423
427
  def write_loop
424
428
  loop do
425
429
  next_action = @write_queue.shift
426
430
  return :stopped if next_action.equal? :STOP!
427
431
  register_action_with_metadata next_action
428
-
432
+
429
433
  ahn_log.ami.debug "Sending AMI action: #{"\n>>> " + next_action.to_s.gsub(/(\r\n)+/, "\n>>> ")}"
430
434
  @actions_connection.send_data next_action.to_s
431
435
  # If it's "causal event" action, we must wait here until it's fully responded
@@ -434,7 +438,7 @@ module Adhearsion
434
438
  rescue => e
435
439
  p e
436
440
  end
437
-
441
+
438
442
  ##
439
443
  # When we send out an AMI action, we need to track the ActionID and have the other Thread handling the socket IO
440
444
  # notify the sending Thread that a response has been received. This method instantiates a new FutureResource and
@@ -451,13 +455,13 @@ module Adhearsion
451
455
  @sent_messages[action.action_id] = action
452
456
  end
453
457
  end
454
-
458
+
455
459
  def data_for_message_received_with_action_id(action_id)
456
460
  @sent_messages_lock.synchronize do
457
461
  @sent_messages.delete action_id
458
462
  end
459
463
  end
460
-
464
+
461
465
  ##
462
466
  # Instantiates a new ManagerInterfaceActionsConnection and assigns it to @actions_connection.
463
467
  #
@@ -471,14 +475,14 @@ module Adhearsion
471
475
  end
472
476
  login_actions
473
477
  end
474
-
478
+
475
479
  ##
476
480
  # Instantiates a new ManagerInterfaceEventsConnection and assigns it to @events_connection.
477
481
  #
478
482
  # @return [EventSocket]
479
483
  #
480
484
  def establish_events_connection
481
-
485
+
482
486
  # Note: the @events_connection instance variable is set in login()
483
487
  @events_connection = EventSocket.connect(@host, @port) do |handler|
484
488
  handler.receive_data { |data| @events_lexer << data }
@@ -499,7 +503,7 @@ module Adhearsion
499
503
  response
500
504
  end
501
505
  end
502
-
506
+
503
507
  ##
504
508
  # Since this method is always called after the login_actions method, an AuthenticationFailedException would have already
505
509
  # been raised if the username/password were off. Because this is the only action we ever need to send on this socket,
@@ -509,7 +513,7 @@ module Adhearsion
509
513
  login_action = ManagerInterfaceAction.new "Login", "Username" => @username, "Secret" => @password, "Events" => "On"
510
514
  @events_connection.send_data login_action.to_s
511
515
  end
512
-
516
+
513
517
  def parse_options(options)
514
518
  unrecognized_keys = options.keys.map { |key| key.to_sym } - DEFAULT_SETTINGS.keys
515
519
  if unrecognized_keys.any?
@@ -517,19 +521,19 @@ module Adhearsion
517
521
  end
518
522
  DEFAULT_SETTINGS.merge options
519
523
  end
520
-
524
+
521
525
  ##
522
526
  # Raised when calling ManagerInterface#connect!() and the server responds with an error after logging in.
523
527
  #
524
528
  class AuthenticationFailedException < Exception; end
525
-
529
+
526
530
  class NotConnectedError < Exception; end
527
-
531
+
528
532
  ##
529
533
  # Each time ManagerInterface#send_action is invoked, a new ManagerInterfaceAction is instantiated.
530
534
  #
531
535
  class ManagerInterfaceAction
532
-
536
+
533
537
  attr_reader :name, :headers, :future_resource, :action_id, :causal_event_terminator_name
534
538
  def initialize(name, headers={})
535
539
  @name = name.to_s.downcase.freeze
@@ -538,7 +542,7 @@ module Adhearsion
538
542
  @future_resource = FutureResource.new
539
543
  @causal_event_terminator_name = ManagerInterface.causal_event_terminator_name_for name
540
544
  end
541
-
545
+
542
546
  ##
543
547
  # Used internally by ManagerInterface for the actions in AMI which break the protocol's definition and do not
544
548
  # reply with an ActionID.
@@ -546,7 +550,7 @@ module Adhearsion
546
550
  def replies_with_action_id?
547
551
  ManagerInterface.replies_with_action_id?(@name, @headers)
548
552
  end
549
-
553
+
550
554
  ##
551
555
  # Some AMI actions effectively respond with many events which collectively constitute the actual response. These
552
556
  # Must be handled specially by the protocol parser, so this method helps inform the parser.
@@ -554,7 +558,7 @@ module Adhearsion
554
558
  def has_causal_events?
555
559
  ManagerInterface.has_causal_events?(@name, @headers)
556
560
  end
557
-
561
+
558
562
  ##
559
563
  # Abstracts the generation of new ActionIDs. This could be implemented virutally any way, provided each
560
564
  # invocation returns something unique, so this will generate a GUID and return it.
@@ -564,7 +568,7 @@ module Adhearsion
564
568
  def new_action_id
565
569
  new_guid # Implemented in lib/adhearsion/foundation/pseudo_guid.rb
566
570
  end
567
-
571
+
568
572
  ##
569
573
  # Converts this action into a protocol-valid String, ready to be sent over a socket.
570
574
  #
@@ -575,7 +579,7 @@ module Adhearsion
575
579
  (@headers.any? ? "\r\n\r\n" : "\r\n")
576
580
  )
577
581
  end
578
-
582
+
579
583
  ##
580
584
  # If the response has simply not been received yet from Asterisk, the calling Thread will block until it comes
581
585
  # in. Once the response comes in, subsequent calls immediately return a reference to the ManagerInterfaceResponse
@@ -584,7 +588,7 @@ module Adhearsion
584
588
  def response
585
589
  future_resource.resource
586
590
  end
587
-
591
+
588
592
  end
589
593
  end
590
594
  end