adhearsion 1.2.6 → 2.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (236) hide show
  1. data/.gitignore +17 -10
  2. data/CHANGELOG.md +273 -0
  3. data/Gemfile +1 -1
  4. data/Guardfile +17 -0
  5. data/README.markdown +61 -9
  6. data/Rakefile +16 -48
  7. data/adhearsion.gemspec +21 -7
  8. data/bin/ahn +3 -1
  9. data/cucumber.yml +4 -0
  10. data/features/app_generator.feature +42 -0
  11. data/features/cli.feature +108 -0
  12. data/features/step_definitions/app_generator_steps.rb +6 -0
  13. data/features/step_definitions/cli_steps.rb +74 -0
  14. data/features/support/aruba_helper.rb +22 -0
  15. data/features/support/env.rb +37 -0
  16. data/features/support/utils.rb +8 -0
  17. data/lib/adhearsion.rb +85 -41
  18. data/lib/adhearsion/call.rb +176 -0
  19. data/lib/adhearsion/call_controller.rb +134 -0
  20. data/lib/adhearsion/call_controller/dial.rb +70 -0
  21. data/lib/adhearsion/call_controller/input.rb +173 -0
  22. data/lib/adhearsion/call_controller/menu.rb +124 -0
  23. data/lib/adhearsion/call_controller/output.rb +267 -0
  24. data/lib/adhearsion/call_controller/record.rb +42 -0
  25. data/lib/adhearsion/call_controller/utility.rb +60 -0
  26. data/lib/adhearsion/calls.rb +81 -0
  27. data/lib/adhearsion/cli.rb +1 -3
  28. data/lib/adhearsion/cli_commands.rb +142 -0
  29. data/lib/adhearsion/configuration.rb +149 -0
  30. data/lib/adhearsion/console.rb +19 -8
  31. data/lib/adhearsion/dialplan_controller.rb +9 -0
  32. data/lib/adhearsion/events.rb +84 -0
  33. data/lib/adhearsion/foundation/all.rb +0 -7
  34. data/lib/adhearsion/foundation/custom_daemonizer.rb +4 -6
  35. data/lib/adhearsion/foundation/exception_handler.rb +9 -0
  36. data/lib/adhearsion/foundation/object.rb +26 -8
  37. data/lib/adhearsion/foundation/synchronized_hash.rb +3 -6
  38. data/lib/adhearsion/foundation/thread_safety.rb +17 -1
  39. data/lib/adhearsion/generators/app/app_generator.rb +4 -13
  40. data/lib/adhearsion/generators/app/templates/Gemfile +10 -5
  41. data/lib/adhearsion/generators/app/templates/Procfile +1 -0
  42. data/lib/adhearsion/generators/app/templates/README.md +28 -0
  43. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +41 -0
  44. data/lib/adhearsion/generators/app/templates/{components/simon_game → lib}/simon_game.rb +6 -18
  45. data/lib/adhearsion/generators/app/templates/script/ahn +2 -2
  46. data/lib/adhearsion/initializer.rb +151 -293
  47. data/lib/adhearsion/initializer/logging.rb +33 -0
  48. data/lib/adhearsion/logging.rb +65 -69
  49. data/lib/adhearsion/menu_dsl.rb +15 -0
  50. data/lib/adhearsion/menu_dsl/calculated_match.rb +39 -0
  51. data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +41 -0
  52. data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +18 -0
  53. data/lib/adhearsion/menu_dsl/match_calculator.rb +36 -0
  54. data/lib/adhearsion/{voip/menu_state_machine/menu_class.rb → menu_dsl/menu.rb} +38 -40
  55. data/lib/adhearsion/menu_dsl/menu_builder.rb +69 -0
  56. data/lib/adhearsion/menu_dsl/range_match_calculator.rb +55 -0
  57. data/lib/adhearsion/menu_dsl/string_match_calculator.rb +21 -0
  58. data/lib/adhearsion/outbound_call.rb +64 -0
  59. data/lib/adhearsion/plugin.rb +319 -0
  60. data/lib/adhearsion/plugin/collection.rb +19 -0
  61. data/lib/adhearsion/plugin/initializer.rb +37 -0
  62. data/lib/adhearsion/plugin/methods_container.rb +6 -0
  63. data/lib/adhearsion/process.rb +94 -0
  64. data/lib/adhearsion/punchblock_plugin.rb +29 -0
  65. data/lib/adhearsion/punchblock_plugin/initializer.rb +137 -0
  66. data/lib/adhearsion/router.rb +30 -0
  67. data/lib/adhearsion/router/route.rb +42 -0
  68. data/lib/adhearsion/script_ahn_loader.rb +2 -2
  69. data/lib/adhearsion/tasks.rb +14 -9
  70. data/lib/adhearsion/tasks/configuration.rb +26 -0
  71. data/lib/adhearsion/tasks/plugins.rb +17 -0
  72. data/lib/adhearsion/version.rb +8 -14
  73. data/spec/adhearsion/call_controller/dial_spec.rb +138 -0
  74. data/spec/adhearsion/call_controller/input_spec.rb +278 -0
  75. data/spec/adhearsion/call_controller/menu_spec.rb +120 -0
  76. data/spec/adhearsion/call_controller/output_spec.rb +466 -0
  77. data/spec/adhearsion/call_controller/record_spec.rb +125 -0
  78. data/spec/adhearsion/call_controller_spec.rb +395 -0
  79. data/spec/adhearsion/call_spec.rb +438 -0
  80. data/spec/adhearsion/calls_spec.rb +47 -0
  81. data/spec/adhearsion/configuration_spec.rb +308 -0
  82. data/spec/adhearsion/dialplan_controller_spec.rb +26 -0
  83. data/spec/adhearsion/events_spec.rb +112 -0
  84. data/spec/adhearsion/initializer/logging_spec.rb +58 -0
  85. data/spec/adhearsion/initializer_spec.rb +209 -122
  86. data/spec/adhearsion/logging_spec.rb +58 -47
  87. data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +56 -0
  88. data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +57 -0
  89. data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +33 -0
  90. data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +13 -0
  91. data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +118 -0
  92. data/spec/adhearsion/menu_dsl/menu_spec.rb +210 -0
  93. data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +28 -0
  94. data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +36 -0
  95. data/spec/adhearsion/menu_dsl_spec.rb +12 -0
  96. data/spec/adhearsion/outbound_call_spec.rb +174 -0
  97. data/spec/adhearsion/plugin_spec.rb +489 -0
  98. data/spec/adhearsion/process_spec.rb +34 -0
  99. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +294 -0
  100. data/spec/adhearsion/router/route_spec.rb +99 -0
  101. data/spec/adhearsion/router_spec.rb +106 -0
  102. data/spec/adhearsion_spec.rb +46 -0
  103. data/spec/spec_helper.rb +14 -14
  104. data/spec/support/call_controller_test_helpers.rb +48 -0
  105. data/spec/support/initializer_stubs.rb +8 -13
  106. data/spec/support/punchblock_mocks.rb +6 -0
  107. metadata +255 -253
  108. data/CHANGELOG +0 -174
  109. data/bin/ahnctl +0 -68
  110. data/bin/jahn +0 -43
  111. data/examples/asterisk_manager_interface/standalone.rb +0 -51
  112. data/lib/adhearsion/commands.rb +0 -302
  113. data/lib/adhearsion/component_manager.rb +0 -278
  114. data/lib/adhearsion/component_manager/component_tester.rb +0 -54
  115. data/lib/adhearsion/component_manager/spec_framework.rb +0 -18
  116. data/lib/adhearsion/events_support.rb +0 -65
  117. data/lib/adhearsion/foundation/blank_slate.rb +0 -3
  118. data/lib/adhearsion/foundation/event_socket.rb +0 -205
  119. data/lib/adhearsion/foundation/future_resource.rb +0 -36
  120. data/lib/adhearsion/foundation/metaprogramming.rb +0 -17
  121. data/lib/adhearsion/foundation/numeric.rb +0 -13
  122. data/lib/adhearsion/foundation/pseudo_guid.rb +0 -10
  123. data/lib/adhearsion/foundation/relationship_properties.rb +0 -42
  124. data/lib/adhearsion/foundation/string.rb +0 -26
  125. data/lib/adhearsion/generators/app/templates/.ahnrc +0 -34
  126. data/lib/adhearsion/generators/app/templates/README +0 -8
  127. data/lib/adhearsion/generators/app/templates/components/ami_remote/ami_remote.rb +0 -15
  128. data/lib/adhearsion/generators/app/templates/components/disabled/HOW_TO_ENABLE +0 -7
  129. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/README.markdown +0 -47
  130. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.rb +0 -34
  131. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.yml +0 -12
  132. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/README.markdown +0 -3
  133. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.rb +0 -11
  134. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.yml +0 -0
  135. data/lib/adhearsion/generators/app/templates/config/startup.rb +0 -81
  136. data/lib/adhearsion/generators/app/templates/dialplan.rb +0 -3
  137. data/lib/adhearsion/generators/app/templates/events.rb +0 -33
  138. data/lib/adhearsion/host_definitions.rb +0 -67
  139. data/lib/adhearsion/initializer/asterisk.rb +0 -86
  140. data/lib/adhearsion/initializer/configuration.rb +0 -324
  141. data/lib/adhearsion/initializer/database.rb +0 -60
  142. data/lib/adhearsion/initializer/drb.rb +0 -31
  143. data/lib/adhearsion/initializer/freeswitch.rb +0 -22
  144. data/lib/adhearsion/initializer/ldap.rb +0 -57
  145. data/lib/adhearsion/initializer/rails.rb +0 -41
  146. data/lib/adhearsion/initializer/xmpp.rb +0 -42
  147. data/lib/adhearsion/tasks/components.rb +0 -32
  148. data/lib/adhearsion/tasks/database.rb +0 -5
  149. data/lib/adhearsion/tasks/deprecations.rb +0 -59
  150. data/lib/adhearsion/tasks/generating.rb +0 -20
  151. data/lib/adhearsion/tasks/lint.rb +0 -4
  152. data/lib/adhearsion/voip/asterisk.rb +0 -4
  153. data/lib/adhearsion/voip/asterisk/agi_server.rb +0 -121
  154. data/lib/adhearsion/voip/asterisk/commands.rb +0 -1966
  155. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +0 -140
  156. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +0 -102
  157. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +0 -250
  158. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +0 -240
  159. data/lib/adhearsion/voip/asterisk/config_manager.rb +0 -64
  160. data/lib/adhearsion/voip/asterisk/manager_interface.rb +0 -697
  161. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +0 -1681
  162. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +0 -341
  163. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +0 -78
  164. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +0 -87
  165. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +0 -80
  166. data/lib/adhearsion/voip/call.rb +0 -521
  167. data/lib/adhearsion/voip/call_routing.rb +0 -64
  168. data/lib/adhearsion/voip/commands.rb +0 -17
  169. data/lib/adhearsion/voip/constants.rb +0 -39
  170. data/lib/adhearsion/voip/conveniences.rb +0 -18
  171. data/lib/adhearsion/voip/dial_plan.rb +0 -252
  172. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +0 -151
  173. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +0 -37
  174. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +0 -27
  175. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +0 -124
  176. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +0 -69
  177. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +0 -16
  178. data/lib/adhearsion/voip/dsl/numerical_string.rb +0 -128
  179. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +0 -48
  180. data/lib/adhearsion/voip/freeswitch/event_handler.rb +0 -58
  181. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +0 -129
  182. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +0 -38
  183. data/lib/adhearsion/voip/freeswitch/oes_server.rb +0 -195
  184. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +0 -80
  185. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +0 -123
  186. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +0 -57
  187. data/lib/adhearsion/xmpp/connection.rb +0 -61
  188. data/lib/theatre.rb +0 -147
  189. data/lib/theatre/README.markdown +0 -64
  190. data/lib/theatre/callback_definition_loader.rb +0 -86
  191. data/lib/theatre/guid.rb +0 -23
  192. data/lib/theatre/invocation.rb +0 -131
  193. data/lib/theatre/namespace_manager.rb +0 -153
  194. data/lib/theatre/version.rb +0 -2
  195. data/spec/adhearsion/cli_spec.rb +0 -306
  196. data/spec/adhearsion/component_manager_spec.rb +0 -292
  197. data/spec/adhearsion/constants_spec.rb +0 -8
  198. data/spec/adhearsion/drb_spec.rb +0 -65
  199. data/spec/adhearsion/fixtures/dialplan.rb +0 -3
  200. data/spec/adhearsion/foundation/event_socket_spec.rb +0 -168
  201. data/spec/adhearsion/host_definitions_spec.rb +0 -79
  202. data/spec/adhearsion/initializer/configuration_spec.rb +0 -291
  203. data/spec/adhearsion/initializer/loading_spec.rb +0 -154
  204. data/spec/adhearsion/initializer/paths_spec.rb +0 -74
  205. data/spec/adhearsion/relationship_properties_spec.rb +0 -54
  206. data/spec/adhearsion/voip/asterisk/agi_server_spec.rb +0 -473
  207. data/spec/adhearsion/voip/asterisk/ami/ami_spec.rb +0 -550
  208. data/spec/adhearsion/voip/asterisk/ami/lexer/ami_fixtures.yml +0 -30
  209. data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story +0 -291
  210. data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story.rb +0 -241
  211. data/spec/adhearsion/voip/asterisk/ami/lexer/story_helper.rb +0 -124
  212. data/spec/adhearsion/voip/asterisk/commands_spec.rb +0 -3241
  213. data/spec/adhearsion/voip/asterisk/config_file_generators/agents_spec.rb +0 -251
  214. data/spec/adhearsion/voip/asterisk/config_file_generators/queues_spec.rb +0 -323
  215. data/spec/adhearsion/voip/asterisk/config_file_generators/voicemail_spec.rb +0 -306
  216. data/spec/adhearsion/voip/asterisk/config_manager_spec.rb +0 -127
  217. data/spec/adhearsion/voip/asterisk/menu_command/calculated_match_spec.rb +0 -109
  218. data/spec/adhearsion/voip/asterisk/menu_command/matchers_spec.rb +0 -97
  219. data/spec/adhearsion/voip/call_routing_spec.rb +0 -125
  220. data/spec/adhearsion/voip/dialplan_manager_spec.rb +0 -468
  221. data/spec/adhearsion/voip/dsl/dialing_dsl_spec.rb +0 -270
  222. data/spec/adhearsion/voip/dsl/dispatcher_spec.rb +0 -82
  223. data/spec/adhearsion/voip/dsl/dispatcher_spec_helper.rb +0 -45
  224. data/spec/adhearsion/voip/dsl/parser_spec.rb +0 -69
  225. data/spec/adhearsion/voip/freeswitch/basic_connection_manager_spec.rb +0 -39
  226. data/spec/adhearsion/voip/freeswitch/inbound_connection_manager_spec.rb +0 -39
  227. data/spec/adhearsion/voip/freeswitch/oes_server_spec.rb +0 -9
  228. data/spec/adhearsion/voip/numerical_string_spec.rb +0 -61
  229. data/spec/adhearsion/voip/phone_number_spec.rb +0 -45
  230. data/spec/support/the_following_code.rb +0 -3
  231. data/spec/theatre/dsl_examples/simple_before_call.rb +0 -7
  232. data/spec/theatre/dsl_spec.rb +0 -69
  233. data/spec/theatre/invocation_spec.rb +0 -182
  234. data/spec/theatre/namespace_spec.rb +0 -125
  235. data/spec/theatre/spec_helper_spec.rb +0 -28
  236. data/spec/theatre/theatre_class_spec.rb +0 -148
@@ -1,341 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'ami_messages.rb')
2
-
3
- module Adhearsion
4
- module VoIP
5
- module Asterisk
6
- module Manager
7
- class AbstractAsteriskManagerInterfaceStreamLexer
8
-
9
- BUFFER_SIZE = 128.kilobytes unless defined? BUFFER_SIZE
10
-
11
- ##
12
- # IMPORTANT! See method documentation for adjust_pointers!
13
- #
14
- # @see adjust_pointers
15
- #
16
- POINTERS = [
17
- :@current_pointer,
18
- :@token_start,
19
- :@token_end,
20
- :@version_start,
21
- :@event_name_start,
22
- :@current_key_position,
23
- :@current_value_position,
24
- :@last_seen_value_end,
25
- :@error_reason_start,
26
- :@follows_text_start,
27
- :@current_syntax_error_start,
28
- :@immediate_response_start
29
- ]
30
-
31
- %%{
32
- machine ami_protocol_parser;
33
-
34
- # All required Ragel actions are implemented as Ruby methods.
35
-
36
- # Executed after a "Response: Success" or "Response: Pong"
37
- action init_success { init_success }
38
-
39
- action init_response_follows { init_response_follows }
40
-
41
- action init_error { init_error }
42
-
43
- action message_received { message_received @current_message }
44
- action error_received { error_received @current_message }
45
-
46
- action version_starts { version_starts }
47
- action version_stops { version_stops }
48
-
49
- action key_starts { key_starts }
50
- action key_stops { key_stops }
51
-
52
- action value_starts { value_starts }
53
- action value_stops { value_stops }
54
-
55
- action error_reason_starts { error_reason_starts }
56
- action error_reason_stops { error_reason_stops }
57
-
58
- action syntax_error_starts { syntax_error_starts }
59
- action syntax_error_stops { syntax_error_stops }
60
-
61
- action immediate_response_starts { immediate_response_starts }
62
- action immediate_response_stops { immediate_response_stops }
63
-
64
- action follows_text_starts { follows_text_starts }
65
- action follows_text_stops { follows_text_stops }
66
-
67
- action event_name_starts { event_name_starts }
68
- action event_name_stops { event_name_stops }
69
-
70
- include ami_protocol_parser_machine "ami_protocol_lexer_machine.rl";
71
-
72
- }%%##
73
-
74
- attr_accessor(:ami_version)
75
- def initialize
76
-
77
- @data = ""
78
- @current_pointer = 0
79
- @ragel_stack = []
80
- @ami_version = 0.0
81
-
82
- %%{
83
- # All other variables become local, letting Ruby garbage collect them. This
84
- # prevents us from having to manually reset them.
85
-
86
- variable data @data;
87
- variable p @current_pointer;
88
- variable pe @data_ending_pointer;
89
- variable cs @current_state;
90
- variable ts @token_start;
91
- variable te @token_end;
92
- variable act @ragel_act;
93
- variable eof @eof;
94
- variable stack @ragel_stack;
95
- variable top @ragel_stack_top;
96
-
97
- write data;
98
- write init;
99
- }%%##
100
-
101
- end
102
-
103
- def <<(new_data)
104
- extend_buffer_with new_data
105
- resume!
106
- end
107
-
108
- def resume!
109
- %%{ write exec; }%%##
110
- end
111
-
112
- def extend_buffer_with(new_data)
113
- length = new_data.size
114
-
115
- if length > BUFFER_SIZE
116
- raise Exception, "ERROR: Buffer overrun! Input size (#{new_data.size}) larger than buffer (#{BUFFER_SIZE})"
117
- end
118
-
119
- if length + @data.size > BUFFER_SIZE
120
- if @data.size != @current_pointer
121
- if @current_pointer < length
122
- # We are about to shift more bytes off the array than we have
123
- # parsed. This will cause the parser to lose state so
124
- # integrity cannot be guaranteed.
125
- raise Exception, "ERROR: Buffer overrun! AMI parser cannot guarantee sanity. New data size: #{new_data.size}; Current pointer at #{@current_pointer}; Data size: #{@data.size}"
126
- end
127
- end
128
- @data.slice! 0...length
129
- adjust_pointers -length
130
- end
131
- @data << new_data
132
- @data_ending_pointer = @data.size
133
- end
134
-
135
- protected
136
-
137
- ##
138
- # This method will adjust all pointers into the buffer according
139
- # to the supplied offset. This is necessary any time the buffer
140
- # changes, for example when the sliding window is incremented forward
141
- # after new data is received.
142
- #
143
- # It is VERY IMPORTANT that when any additional pointers are defined
144
- # that they are added to this method. Unpredictable results may
145
- # otherwise occur!
146
- #
147
- # @see https://adhearsion.lighthouseapp.com/projects/5871-adhearsion/tickets/72-ami-lexer-buffer-offset#ticket-72-26
148
- #
149
- # @param offset Adjust pointers by offset. May be negative.
150
- #
151
- def adjust_pointers(offset)
152
- POINTERS.each do |ptr|
153
- value = instance_variable_get(ptr)
154
- instance_variable_set(ptr, value + offset) if !value.nil?
155
- end
156
- end
157
-
158
- ##
159
- # Called after a response or event has been successfully parsed.
160
- #
161
- # @param [ManagerInterfaceResponse, ManagerInterfaceEvent] message The message just received
162
- #
163
- def message_received(message)
164
- raise NotImplementedError, "Must be implemented in subclass!"
165
- end
166
-
167
- ##
168
- # Called when there is an Error: stanza on the socket. Could be caused by executing an unrecognized command, trying
169
- # to originate into an invalid priority, etc. Note: many errors' responses are actually tightly coupled to a
170
- # ManagerInterfaceEvent which comes directly after it. Often the message will say something like "Channel status
171
- # will follow".
172
- #
173
- # @param [String] reason The reason given in the Message: header for the error stanza.
174
- #
175
- def error_received(reason)
176
- raise NotImplementedError, "Must be implemented in subclass!"
177
- end
178
-
179
- ##
180
- # Called when there's a syntax error on the socket. This doesn't happen as often as it should because, in many cases,
181
- # it's impossible to distinguish between a syntax error and an immediate packet.
182
- #
183
- # @param [String] ignored_chunk The offending text which caused the syntax error.
184
- def syntax_error_encountered(ignored_chunk)
185
- raise NotImplementedError, "Must be implemented in subclass!"
186
- end
187
-
188
- def init_success
189
- @current_message = ManagerInterfaceResponse.new
190
- end
191
-
192
- def init_response_follows
193
- @current_message = ManagerInterfaceResponse.new
194
- end
195
-
196
- def init_error
197
- @current_message = ManagerInterfaceError.new()
198
- end
199
-
200
- def version_starts
201
- @version_start = @current_pointer
202
- end
203
-
204
- def version_stops
205
- self.ami_version = @data[@version_start...@current_pointer].to_f
206
- @version_start = nil
207
- end
208
-
209
- def event_name_starts
210
- @event_name_start = @current_pointer
211
- end
212
-
213
- def event_name_stops
214
- event_name = @data[@event_name_start...@current_pointer]
215
- @event_name_start = nil
216
- @current_message = ManagerInterfaceEvent.new(event_name)
217
- end
218
-
219
- def key_starts
220
- @current_key_position = @current_pointer
221
- end
222
-
223
- def key_stops
224
- @current_key = @data[@current_key_position...@current_pointer]
225
- end
226
-
227
- def value_starts
228
- @current_value_position = @current_pointer
229
- end
230
-
231
- def value_stops
232
- @current_value = @data[@current_value_position...@current_pointer]
233
- @last_seen_value_end = @current_pointer + 2 # 2 for \r\n
234
- add_pair_to_current_message
235
- end
236
-
237
- def error_reason_starts
238
- @error_reason_start = @current_pointer
239
- end
240
-
241
- def error_reason_stops
242
- @current_message.message = @data[@error_reason_start...@current_pointer]
243
- end
244
-
245
- def follows_text_starts
246
- @follows_text_start = @current_pointer
247
- end
248
-
249
- def follows_text_stops
250
- text = @data[@last_seen_value_end..@current_pointer]
251
- text.sub! /\r?\n--END COMMAND--/, ""
252
- @current_message.text_body = text
253
- @follows_text_start = nil
254
- end
255
-
256
- def add_pair_to_current_message
257
- @current_message[@current_key] = @current_value
258
- reset_key_and_value_positions
259
- end
260
-
261
- def reset_key_and_value_positions
262
- @current_key, @current_value, @current_key_position, @current_value_position = nil
263
- end
264
-
265
- def syntax_error_starts
266
- @current_syntax_error_start = @current_pointer # Adding 1 since the pointer is still set to the last successful match
267
- end
268
-
269
- def syntax_error_stops
270
- # Subtracting 3 from @current_pointer below for "\r\n" which separates a stanza
271
- offending_data = @data[@current_syntax_error_start...@current_pointer - 1]
272
- syntax_error_encountered offending_data
273
- @current_syntax_error_start = nil
274
- end
275
-
276
- def immediate_response_starts
277
- @immediate_response_start = @current_pointer
278
- end
279
-
280
- def immediate_response_stops
281
- message = @data[@immediate_response_start...(@current_pointer -1)]
282
- message_received ManagerInterfaceResponse.from_immediate_response(message)
283
- end
284
-
285
- ##
286
- # This method is used primarily in debugging.
287
- #
288
- def view_buffer(message=nil)
289
-
290
- message ||= "Viewing the buffer"
291
-
292
- buffer = @data.clone
293
- buffer.insert(@current_pointer, "\033[0;31m\033[1;31m^\033[0m")
294
-
295
- buffer.gsub!("\r", "\\\\r")
296
- buffer.gsub!("\n", "\\n\n")
297
-
298
- puts <<-INSPECTION
299
- VVVVVVVVVVVVVVVVVVVVVVVVVVVVV
300
- #### #{message}
301
- #############################
302
- #{buffer}
303
- #############################
304
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
305
- INSPECTION
306
-
307
- end
308
- end
309
- class DelegatingAsteriskManagerInterfaceLexer < AbstractAsteriskManagerInterfaceStreamLexer
310
-
311
- def initialize(delegate, method_delegation_map=nil)
312
- super()
313
- @delegate = delegate
314
-
315
- @message_received_method = method_delegation_map && method_delegation_map.has_key?(:message_received) ?
316
- method_delegation_map[:message_received] : :message_received
317
-
318
- @error_received_method = method_delegation_map && method_delegation_map.has_key?(:error_received) ?
319
- method_delegation_map[:error_received] : :error_received
320
-
321
- @syntax_error_method = method_delegation_map && method_delegation_map.has_key?(:syntax_error_encountered) ?
322
- method_delegation_map[:syntax_error_encountered] : :syntax_error_encountered
323
- end
324
-
325
- def message_received(message)
326
- @delegate.send(@message_received_method, message)
327
- end
328
-
329
- def error_received(message)
330
- @delegate.send(@error_received_method, message)
331
- end
332
-
333
- def syntax_error_encountered(ignored_chunk)
334
- @delegate.send(@syntax_error_method, ignored_chunk)
335
- end
336
-
337
- end
338
- end
339
- end
340
- end
341
- end
@@ -1,78 +0,0 @@
1
- module Adhearsion
2
- module VoIP
3
- module Asterisk
4
- module Manager
5
-
6
-
7
- ##
8
- # This is the object containing a response from Asterisk.
9
- #
10
- # Note: not all responses have an ActionID!
11
- #
12
- class ManagerInterfaceResponse
13
-
14
- class << self
15
- def from_immediate_response(text)
16
- new.tap do |instance|
17
- instance.text_body = text
18
- end
19
- end
20
- end
21
-
22
- attr_accessor :action,
23
- :action_id,
24
- :text_body # For "Response: Follows" sections
25
- attr_reader :events
26
-
27
- def initialize
28
- @headers = HashWithIndifferentAccess.new
29
- end
30
-
31
- def has_text_body?
32
- !! @text_body
33
- end
34
-
35
- def headers
36
- @headers.clone
37
- end
38
-
39
- def [](arg)
40
- @headers[arg]
41
- end
42
-
43
- def []=(key,value)
44
- @headers[key] = value
45
- end
46
-
47
- end
48
-
49
- class ManagerInterfaceError < StandardError
50
-
51
- attr_accessor :message
52
- def initialize
53
- @headers = HashWithIndifferentAccess.new
54
- end
55
-
56
- def [](key)
57
- @headers[key]
58
- end
59
-
60
- def []=(key,value)
61
- @headers[key] = value
62
- end
63
-
64
- end
65
-
66
- class ManagerInterfaceEvent < ManagerInterfaceResponse
67
-
68
- attr_reader :name
69
- def initialize(name)
70
- super()
71
- @name = name
72
- end
73
-
74
- end
75
- end
76
- end
77
- end
78
- end
@@ -1,87 +0,0 @@
1
- %%{ #%
2
-
3
- #########
4
- ## This file is written with the Ragel programming language and parses the Asterisk Manager Interface protocol. It depends
5
- ## upon Ragel actions which should be implemented in another Ragel-parsed file which includes this file.
6
- ##
7
- ## Ragel was used because the AMI protocol is extremely non-deterministic and, in the edge cases, requires something both
8
- ## very robust and something which can recover from syntax errors.
9
- ##
10
- ## Note: This file is language agnostic. From this AMI parsers in many other languages can be generated.
11
- #########
12
-
13
- machine ami_protocol_parser_machine;
14
-
15
- cr = "\r"; # A carriage return. Used before (almost) every newline character.
16
- lf = "\n"; # Newline. Used (with cr) to separate key/value pairs and stanzas.
17
- crlf = cr lf; # Means "carriage return and line feed". Used to separate key/value pairs and stanzas
18
- loose_newline = cr? lf; # Used sometimes when the AMI protocol is nondeterministic about the delimiter
19
-
20
- white = [\t ]; # Single whitespace character, either a tab or a space
21
- colon = ":" [ ]**; # Separates keys from values. "A colon followed by any number of spaces"
22
- stanza_break = crlf crlf; # The seperator between two stanzas.
23
- rest_of_line = (any* -- crlf); # Match all characters until the next line seperator.
24
-
25
- Prompt = "Asterisk Call Manager/" digit+ >version_starts "." digit+ %version_stops crlf;
26
-
27
- Key = ((alnum | print) -- (cr | lf | ":"))+;
28
- KeyValuePair = Key >key_starts %key_stops colon rest_of_line >value_starts %value_stops crlf;
29
-
30
- FollowsDelimiter = loose_newline "--END COMMAND--";
31
-
32
- Response = "Response"i colon;
33
-
34
- Success = Response "Success"i %init_success crlf @{ fgoto success; };
35
- Pong = Response "Pong"i %init_success crlf @{ fgoto success; };
36
- Event = "Event"i colon %event_name_starts rest_of_line %event_name_stops crlf @{ fgoto success; };
37
- Error = Response "Error"i %init_error crlf (("Message"i colon rest_of_line >error_reason_starts crlf >error_reason_stops) | KeyValuePair)+ crlf @error_received;
38
- Follows = Response "Follows"i crlf @init_response_follows @{ fgoto response_follows; };
39
-
40
- # For "Response: Follows"
41
- FollowsBody = (any* -- FollowsDelimiter) >follows_text_starts FollowsDelimiter @follows_text_stops crlf;
42
-
43
- ImmediateResponse = (any+ -- (loose_newline | ":")) >immediate_response_starts loose_newline @immediate_response_stops @{fret;};
44
- SyntaxError = (any+ -- crlf) >syntax_error_starts crlf @syntax_error_stops;
45
-
46
- irregularity := |*
47
- ImmediateResponse; # Performs the fret in the ImmediateResponse FSM
48
- SyntaxError => { fret; };
49
- *|;
50
-
51
- # When a new socket is established, Asterisk will send the version of the protocol per the Prompt machine. Because it's
52
- # tedious for unit tests to always send this, we'll put some intelligence into this parser to support going straight into
53
- # the protocol-parsing machine. It's also conceivable that a variant of AMI would not send this initial information.
54
- main := |*
55
- Prompt => { fgoto protocol; };
56
- any => {
57
- # If this scanner's look-ahead capability didn't match the prompt, let's ignore the need for a prompt
58
- fhold;
59
- fgoto protocol;
60
- };
61
- *|;
62
-
63
- protocol := |*
64
- Prompt;
65
- Success;
66
- Pong;
67
- Event;
68
- Error;
69
- Follows crlf;
70
- crlf => { fgoto protocol; }; # If we get a crlf out of place, let's just ignore it.
71
- any => {
72
- # If NONE of the above patterns match, we consider this a syntax error. The irregularity machine can recover gracefully.
73
- fhold;
74
- fcall irregularity;
75
- };
76
- *|;
77
-
78
- success := KeyValuePair* crlf @message_received @{fgoto protocol;};
79
-
80
- # For the "Response: Follows" protocol abnormality. What happens if there's a protocol irregularity in this state???
81
- response_follows := |*
82
- KeyValuePair+;
83
- FollowsBody;
84
- crlf @{ message_received @current_message; fgoto protocol; };
85
- *|;
86
-
87
- }%%