ruby_ami 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+
6
+ lib/ruby_ami/lexer.rb
7
+ .rvmrc
8
+ .yardoc
9
+ doc
10
+ coverage
11
+ spec/reports
12
+ features/reports
13
+ vendor
14
+ *.swp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --colour
3
+ --tty
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # develop
2
+
3
+ # 0.1.1
4
+ * Bugfix: Make countdownlatch and i18n runtime dependencies
5
+ * Bugfig: Include the generated lexer file in the gem
6
+
7
+ # 0.1.0
8
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ruby_ami.gemspec
4
+ gemspec
5
+
6
+ if RUBY_PLATFORM =~ /darwin/
7
+ gem 'growl_notify'
8
+ gem 'rb-fsevent'
9
+ end
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec', :version => 2, :cli => '--format documentation' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec/" }
5
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ben Langfeld, Jay Phillips
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # RubyAMI
2
+ RubyAMI is an AMI client library in Ruby and based on EventMachine with the sole purpose of providing an connection to the Asterisk Manager Interface. RubyAMI does not provide any features beyond connection management and protocol parsing. Actions are sent over the wire, and responses come back via callbacks. It's up to you to match these up into something useful. In this regard, RubyAMI is very similar to [Blather](https://github.com/sprsquish/blather) for XMPP or [Punchblock](https://github.com/adhearsion/punchblock), the Ruby 3PCC library. In fact, Punchblock uses RubyAMI under the covers for its Asterisk implementation, including an implementation of AsyncAGI.
3
+
4
+ ## Installation
5
+ gem install ruby_ami
6
+
7
+ ## Usage
8
+ ```ruby
9
+ require 'ruby_ami'
10
+
11
+ class MyAMIClient < RubyAMI::Client
12
+ def on_connect
13
+ puts "AMI Connected successfully"
14
+ write_action "Originate", ...some options...
15
+ end
16
+
17
+ def handle_event(event)
18
+ puts "Received an AMI event: #{event}"
19
+ end
20
+
21
+ def handle_error(error)
22
+ ...similar here...
23
+ end
24
+
25
+ def handle_response(response)
26
+ ...similar here...
27
+ end
28
+ end
29
+
30
+ EM.run { MyAMIClient.run '127.0.0.1', 5038, 'admin', 'password' }
31
+ ```
32
+
33
+ ## Links:
34
+ * [Source](https://github.com/adhearsion/ruby_ami)
35
+ * [Documentation](http://rdoc.info/github/adhearsion/ruby_ami/master/frames)
36
+ * [Bug Tracker](https://github.com/adhearsion/ruby_ami/issues)
37
+
38
+ ## Note on Patches/Pull Requests
39
+
40
+ * Fork the project.
41
+ * Make your feature addition or bug fix.
42
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
43
+ * Commit, do not mess with rakefile, version, or history.
44
+ * If you want to have your own version, that is fine but bump version in a commit by itself so I can ignore when I pull
45
+ * Send me a pull request. Bonus points for topic branches.
46
+
47
+ ## Copyright
48
+
49
+ Copyright (c) 2011 Ben Langfeld, Jay Phillips. MIT licence (see LICENSE for details).
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+ require 'ci/reporter/rake/rspec'
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = 'spec/**/*_spec.rb'
8
+ spec.rspec_opts = '--color'
9
+ end
10
+
11
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
12
+ spec.pattern = 'spec/**/*_spec.rb'
13
+ spec.rcov = true
14
+ spec.rspec_opts = '--color'
15
+ end
16
+
17
+ require 'cucumber'
18
+ require 'cucumber/rake/task'
19
+ require 'ci/reporter/rake/cucumber'
20
+ Cucumber::Rake::Task.new(:features) do |t|
21
+ t.cucumber_opts = %w{--tags ~@jruby} unless defined?(JRUBY_VERSION)
22
+ end
23
+
24
+ Cucumber::Rake::Task.new(:wip) do |t|
25
+ t.cucumber_opts = %w{-p wip}
26
+ end
27
+
28
+ task :default => [:ragel, :spec, :features]
29
+ task :ci => [:ragel, 'ci:setup:rspec', :spec, 'ci:setup:cucumber', :features]
30
+
31
+ require 'yard'
32
+ YARD::Rake::YardocTask.new
33
+
34
+ desc "Check Ragel version"
35
+ task :check_ragel_version do
36
+ ragel_version_match = `ragel --version`.match /(\d)\.(\d)+/
37
+ abort "Could not get Ragel version! Is it installed? You must have at least version 6.3" unless ragel_version_match
38
+ big, small = ragel_version_match.captures.map &:to_i
39
+ if big < 6 || (big == 6 && small < 3)
40
+ abort "Please upgrade Ragel! You're on version #{ragel_version_match[0]} and must be on 6.3 or later"
41
+ end
42
+ if (big == 6 && small < 7)
43
+ puts "WARNING: A change to Ruby since 1.9 affects the Ragel generated code."
44
+ puts "WARNING: You MUST be using Ragel version 6.7 or have patched it using"
45
+ puts "WARNING: the patch found at:"
46
+ puts "WARNING: http://www.mail-archive.com/ragel-users@complang.org/msg00440.html"
47
+ end
48
+ end
49
+
50
+ RAGEL_FILES = %w[lib/ruby_ami/lexer.rl.rb]
51
+
52
+ desc "Used to regenerate the AMI source code files. Note: requires Ragel 6.3 or later be installed on your system"
53
+ task :ragel => :check_ragel_version do
54
+ RAGEL_FILES.each do |ragel_file|
55
+ ruby_file = ragel_file.sub ".rl.rb", ".rb"
56
+ puts `ragel -n -R #{ragel_file} -o #{ruby_file} 2>&1`
57
+ raise "Failed generating code from Ragel file #{ragel_file}" if $?.to_i.nonzero?
58
+ end
59
+ end
60
+
61
+ desc "Generates a GraphVis document showing the Ragel state machine"
62
+ task :visualize_ragel => :check_ragel_version do
63
+ RAGEL_FILES.each do |ragel_file|
64
+ base_name = File.basename ragel_file, ".rl.rb"
65
+ puts "ragel -V #{ragel_file} -o #{base_name}.dot 2>&1"
66
+ puts `ragel -V #{ragel_file} -o #{base_name}.dot 2>&1`
67
+ raise "Failed generating code from Ragel file #{ragel_file}" if $?.to_i.nonzero?
68
+ end
69
+ end
data/cucumber.yml ADDED
@@ -0,0 +1,2 @@
1
+ default: --tags ~@wip
2
+ wip: --wip --tags @wip
@@ -0,0 +1,260 @@
1
+ Feature: Lexing AMI
2
+ As a RubyAMI user
3
+ I want to lex the AMI protocol
4
+ So that I can control Asterisk asynchronously
5
+
6
+ Scenario: Lexing only the initial AMI version header
7
+ Given a new lexer
8
+ And a version header for AMI 1.0
9
+
10
+ When the buffer is lexed
11
+
12
+ Then the protocol should have lexed without syntax errors
13
+ And the version should be set to 1.0
14
+
15
+ Scenario: Lexing the initial AMI header and a login attempt
16
+ Given a new lexer
17
+ And a version header for AMI 1.0
18
+ And a normal login success with events
19
+
20
+ When the buffer is lexed
21
+
22
+ Then the protocol should have lexed without syntax errors
23
+ And 1 message should have been received
24
+
25
+ Scenario: Lexing the initial AMI header and then a Response:Follows section
26
+ Given a new lexer
27
+ And a version header for AMI 1.0
28
+ And a multi-line Response:Follows body of ragel_description
29
+
30
+ When the buffer is lexed
31
+
32
+ Then the protocol should have lexed without syntax errors
33
+ And the 'follows' body of 1 message received should equal ragel_description
34
+
35
+ Scenario: Lexing a Response:Follows section with no body
36
+ Given a new lexer
37
+ And a version header for AMI 1.0
38
+ And a multi-line Response:Follows body of empty_String
39
+
40
+ When the buffer is lexed
41
+
42
+ Then the protocol should have lexed without syntax errors
43
+ And the 'follows' body of 1 message received should equal empty_string
44
+
45
+ Scenario: Lexing a multi-line Response:Follows simulating the "core show channels" command
46
+ Given a new lexer
47
+ And a version header for AMI 1.0
48
+ Given a multi-line Response:Follows body of show_channels_from_wayne
49
+
50
+ When the buffer is lexed
51
+
52
+ Then the protocol should have lexed without syntax errors
53
+ And the 'follows' body of 1 message received should equal show_channels_from_wayne
54
+
55
+ Scenario: Lexing a multi-line Response:Follows simulating the "core show uptime" command
56
+ Given a new lexer
57
+ And a version header for AMI 1.0
58
+ Given a multi-line Response:Follows response simulating uptime
59
+
60
+ When the buffer is lexed
61
+
62
+ Then the protocol should have lexed without syntax errors
63
+ And the first message received should have a key "System uptime" with value "46 minutes, 30 seconds"
64
+
65
+ Scenario: Lexing a Response:Follows section which has a colon not on the first line
66
+ Given a new lexer
67
+ And a multi-line Response:Follows body of with_colon_after_first_line
68
+
69
+ When the buffer is lexed
70
+
71
+ Then the protocol should have lexed without syntax errors
72
+ And 1 message should have been received
73
+ And the 'follows' body of 1 message received should equal with_colon_after_first_line
74
+
75
+ @wip
76
+ Scenario: Lexing an immediate response with a colon in it.
77
+ Given a new lexer
78
+ And an immediate response with text "markq has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime), W:0, C:0, A:0, SL:0.0% within 0s\r\n No Members\r\n No Callers\r\n\r\n\r\n\r\n"
79
+
80
+ When the buffer is lexed
81
+
82
+ Then the protocol should have lexed without syntax errors
83
+ And 1 message should have been received
84
+ And 1 message should be an immediate response with text "markq has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime), W:0, C:0, A:0, SL:0.0% within 0s\r\n No Members\r\n No Callers"
85
+
86
+ Scenario: Lexing the initial AMI header and then an "Authentication Required" error.
87
+ Given a new lexer
88
+ And a version header for AMI 1.0
89
+ And an Authentication Required error
90
+
91
+ When the buffer is lexed
92
+
93
+ Then the protocol should have lexed without syntax errors
94
+
95
+ Scenario: Lexing the initial AMI header and then a Response:Follows section
96
+ Given a new lexer
97
+ And a version header for AMI 1.0
98
+ And a multi-line Response:Follows body of ragel_description
99
+ And a multi-line Response:Follows body of ragel_description
100
+
101
+ When the buffer is lexed
102
+
103
+ Then the protocol should have lexed without syntax errors
104
+ And the 'follows' body of 2 messages received should equal ragel_description
105
+
106
+ Scenario: Lexing a stanza without receiving an AMI header
107
+ Given a new lexer
108
+ And a normal login success with events
109
+
110
+ When the buffer is lexed
111
+
112
+ Then the protocol should have lexed without syntax errors
113
+ And 1 message should have been received
114
+
115
+ Scenario: Receiving an immediate response as soon as the socket is opened
116
+ Given a new lexer
117
+ And an immediate response with text "Immediate responses are so ridiculous"
118
+
119
+ When the buffer is lexed
120
+
121
+ Then the protocol should have lexed without syntax errors
122
+ And 1 message should have been received
123
+ And 1 message should be an immediate response with text "Immediate responses are so ridiculous"
124
+
125
+ Scenario: Receiving an immediate message surrounded by real messages
126
+ Given a new lexer
127
+ And a normal login success with events
128
+ And an immediate response with text "No queues have been created."
129
+ And a normal login success with events
130
+
131
+ When the buffer is lexed
132
+
133
+ Then the protocol should have lexed without syntax errors
134
+ And 3 messages should have been received
135
+ And 1 message should be an immediate response with text "No queues have been created."
136
+
137
+ Scenario: Receiving a Pong after a simulated login
138
+ Given a new lexer
139
+ And a version header for AMI 1.0
140
+ And a normal login success with events
141
+ And a Pong response with an ActionID of randomness
142
+
143
+ When the buffer is lexed
144
+
145
+ Then the protocol should have lexed without syntax errors
146
+ And 2 messages should have been received
147
+
148
+ Scenario: Ten Pong responses in a row
149
+ Given a new lexer
150
+ And 5 Pong responses without an ActionID
151
+ And 5 Pong responses with an ActionID of randomness
152
+
153
+ When the buffer is lexed
154
+
155
+ Then the protocol should have lexed without syntax errors
156
+ And 10 messages should have been received
157
+
158
+ Scenario: A Pong with an ActionID
159
+ Given a new lexer
160
+ And a Pong response with an ActionID of 1224469850.61673
161
+
162
+ When the buffer is lexed
163
+
164
+ Then the first message received should have a key "ActionID" with value "1224469850.61673"
165
+
166
+ Scenario: A response containing a floating point value
167
+ Given a new lexer
168
+ And a custom stanza named "call"
169
+ And the custom stanza named "call" has key "ActionID" with value "1224469850.61673"
170
+ And the custom stanza named "call" has key "Uniqueid" with value "1173223225.10309"
171
+
172
+ When the custom stanza named "call" is added to the buffer
173
+ And the buffer is lexed
174
+
175
+ Then the 1st message received should have a key "Uniqueid" with value "1173223225.10309"
176
+
177
+ Scenario: Receiving a message with custom key/value pairs
178
+ Given a new lexer
179
+ And a custom stanza named "person"
180
+ And the custom stanza named "person" has key "ActionID" with value "1224469850.61673"
181
+ And the custom stanza named "person" has key "Name" with value "Jay Phillips"
182
+ And the custom stanza named "person" has key "Age" with value "21"
183
+ And the custom stanza named "person" has key "Location" with value "San Francisco, CA"
184
+ And the custom stanza named "person" has key "x-header" with value "<FooBAR>"
185
+ And the custom stanza named "person" has key "Channel" with value "IAX2/127.0.0.1/4569-9904"
186
+ And the custom stanza named "person" has key "I have spaces" with value "i have trailing padding "
187
+
188
+ When the custom stanza named "person" is added to the buffer
189
+ And the buffer is lexed
190
+
191
+ Then the protocol should have lexed without syntax errors
192
+ And the first message received should have a key "Name" with value "Jay Phillips"
193
+ And the first message received should have a key "ActionID" with value "1224469850.61673"
194
+ And the first message received should have a key "Name" with value "Jay Phillips"
195
+ And the first message received should have a key "Age" with value "21"
196
+ And the first message received should have a key "Location" with value "San Francisco, CA"
197
+ And the first message received should have a key "x-header" with value "<FooBAR>"
198
+ And the first message received should have a key "Channel" with value "IAX2/127.0.0.1/4569-9904"
199
+ And the first message received should have a key "I have spaces" with value "i have trailing padding "
200
+
201
+ Scenario: Executing a stanza that was partially received
202
+ Given a new lexer
203
+ And a normal login success with events split into two pieces
204
+
205
+ When the buffer is lexed
206
+
207
+ Then the protocol should have lexed without syntax errors
208
+ And 1 message should have been received
209
+
210
+ Scenario: Receiving an AMI error followed by a normal event
211
+ Given a new lexer
212
+ And an AMI error whose message is "Missing action in request"
213
+ And a normal login success with events
214
+
215
+ When the buffer is lexed
216
+
217
+ Then the protocol should have lexed without syntax errors
218
+ And 1 AMI error should have been received
219
+ And the 1st AMI error should have the message "Missing action in request"
220
+ And 1 message should have been received
221
+
222
+ Scenario: Lexing an immediate response
223
+ Given a new lexer
224
+ And a normal login success with events
225
+ And an immediate response with text "Yes, plain English is sent sometimes over AMI."
226
+ And a normal login success with events
227
+
228
+ When the buffer is lexed
229
+
230
+ Then the protocol should have lexed without syntax errors
231
+ And 3 messages should have been received
232
+ And 1 message should be an immediate response with text "Yes, plain English is sent sometimes over AMI."
233
+
234
+ Scenario: Lexing an AMI event
235
+ Given a new lexer
236
+ And a custom event with name "NewChannelEvent" identified by "this_event"
237
+ And a custom header for event identified by "this_event" whose key is "Foo" and value is "Bar"
238
+ And a custom header for event identified by "this_event" whose key is "Channel" and value is "IAX2/127.0.0.1:4569-9904"
239
+ And a custom header for event identified by "this_event" whose key is "AppData" and value is "agi://localhost"
240
+
241
+ When the custom event identified by "this_event" is added to the buffer
242
+ And the buffer is lexed
243
+
244
+ Then the protocol should have lexed without syntax errors
245
+ And 1 event should have been received
246
+ And the 1st event should have the name "NewChannelEvent"
247
+ And the 1st event should have key "Foo" with value "Bar"
248
+ And the 1st event should have key "Channel" with value "IAX2/127.0.0.1:4569-9904"
249
+ And the 1st event should have key "AppData" with value "agi://localhost"
250
+
251
+ Scenario: Lexing an immediate packet with a colon in it (syntax error)
252
+ Given a new lexer
253
+ And syntactically invalid immediate_packet_with_colon
254
+ And a stanza break
255
+
256
+ When the buffer is lexed
257
+
258
+ Then 0 messages should have been received
259
+ And the protocol should have lexed with 1 syntax error
260
+ And the syntax error fixture named immediate_packet_with_colon should have been encountered