adhearsion 1.2.6 → 2.0.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- }%%