ruby_ami 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5953bb5e6fa27b0deeee4847c2a858ac569fcc0a
4
+ data.tar.gz: 55cf2a66637e697c1395e89da1ae2c6d79dd05cf
5
+ SHA512:
6
+ metadata.gz: a98f86436f743270e3d0950a3056ac3ed673df03648379726a86a28717cc059688f94aded13b090c98cb25e7456a2c61af60179d2702dcacd53dd2ed5d4e298f
7
+ data.tar.gz: d5a21a2b1bd5e35813a38d724415a3acd519a4461e9690ef0e2bd177a1d74037c3bc2cf62bc34748b4b8c447866130ac996fb7b87763f4901e081c31a8a2a8cb
@@ -1,5 +1,11 @@
1
1
  # [develop](https://github.com/adhearsion/ruby_ami)
2
2
 
3
+ # [2.3.0](https://github.com/adhearsion/ruby_ami/compare/v2.2.1...v2.3.0) - [2015-06-01](https://rubygems.org/gems/ruby_ami/versions/2.3.0)
4
+ * Feature: Allow optional error handler when calling `send_action`
5
+ * Bugfix: Catch for Errno::HOSTUNREACH error when connecting to AMI
6
+ * Bugfix: Add support for Goodbye responses instead of processing them as syntax errors
7
+ * Bugfix: Allow simple example of event handling (switching on `event.name` only) to work by giving connection status events a name to match their class names
8
+
3
9
  # [2.2.1](https://github.com/adhearsion/ruby_ami/compare/v2.2.0...v2.2.1) - [2014-05-22](https://rubygems.org/gems/ruby_ami/versions/2.2.1)
4
10
  * Bugfix: Ensure DateTime is present when consumer code doesn't `require 'time'` ([#24](https://github.com/adhearsion/ruby_ami/issues/24))
5
11
 
data/README.md CHANGED
@@ -1,4 +1,12 @@
1
- # RubyAMI [![Build Status](https://secure.travis-ci.org/adhearsion/ruby_ami.png?branch=master)](http://travis-ci.org/adhearsion/ruby_ami)
1
+ # RubyAMI
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/ruby_ami.png)](https://rubygems.org/gems/ruby_ami)
4
+ [![Build Status](https://secure.travis-ci.org/adhearsion/ruby_ami.png?branch=develop)](http://travis-ci.org/adhearsion/ruby_ami)
5
+ [![Dependency Status](https://gemnasium.com/adhearsion/ruby_ami.png?travis)](https://gemnasium.com/adhearsion/ruby_ami)
6
+ [![Code Climate](https://codeclimate.com/github/adhearsion/ruby_ami.png)](https://codeclimate.com/github/adhearsion/ruby_ami)
7
+ [![Coverage Status](https://coveralls.io/repos/adhearsion/ruby_ami/badge.png?branch=develop)](https://coveralls.io/r/adhearsion/ruby_ami)
8
+ [![Inline docs](http://inch-ci.org/github/adhearsion/ruby_ami.png?branch=develop)](http://inch-ci.org/github/adhearsion/ruby_ami)
9
+
2
10
  RubyAMI is an AMI client library in Ruby and based on EventMachine with the sole purpose of providing a 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 are returned. Events are passed to a callback you define. 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
11
 
4
12
  NB: If you're looking to develop an application on Asterisk, you should take a look at the [Adhearsion](http://adhearsion.com) framework first. This library is much lower level.
@@ -10,20 +18,18 @@ NB: If you're looking to develop an application on Asterisk, you should take a l
10
18
  ```ruby
11
19
  require 'ruby_ami'
12
20
 
13
- stream = RubyAMI::Stream.new '127.0.0.1', 5038, 'manager', 'password',
21
+ $stream = RubyAMI::Stream.new '127.0.0.1', 5038, 'manager', 'password',
14
22
  ->(e) { handle_event e },
15
23
  Logger.new(STDOUT), 10
16
24
 
17
25
  def handle_event(event)
18
26
  case event.name
19
27
  when 'FullyBooted'
20
- stream.async.send_action 'Originate', 'Channel' => 'SIP/foo'
28
+ $stream.async.send_action 'Originate', 'Channel' => 'SIP/foo'
21
29
  end
22
30
  end
23
31
 
24
- stream.start
25
-
26
- Celluloid::Actor.join stream
32
+ $stream.run # This will block until the actor is terminated elsewhere. $stream.async.run is also available if you need to do other things in the main thread.
27
33
  ```
28
34
 
29
35
  RubyAMI also has a class called `RubyAMI::Client` which used to be the main usage method. The purpose of this class was to tie together two AMI connections and separate events and action execution between the two in order to avoid some issues present in Asterisk < 1.8 with regards to separating overlapping events and executing multiple actions simultaneously. These issues are no longer present, and so **`RubyAMI::Client` is now deprecated and will be removed in RubyAMI 3.0**.
@@ -11,10 +11,11 @@ module RubyAMI
11
11
  EVENT = /event: *(?<event_name>.*)?/i
12
12
  ERROR = /response: *error/i
13
13
  FOLLOWS = /response: *follows/i
14
+ GOODBYE = /response: *goodbye/i
14
15
  SCANNER = /.*?#{STANZA_BREAK}/m
15
16
  HEADER_SLICE = /.*\r\n/
16
17
  IMMEDIATE_RESP = /.*/
17
- CLASSIFIER = /((?<event>#{EVENT})|(?<success>#{SUCCESS})|(?<pong>#{PONG})|(?<follows>#{FOLLOWS})|(?<error>#{ERROR})|(?<immediate>#{IMMEDIATE_RESP})\r\n)\r\n/i
18
+ CLASSIFIER = /((?<event>#{EVENT})|(?<success>#{SUCCESS})|(?<pong>#{PONG})|(?<follows>#{FOLLOWS})|(?<error>#{ERROR})|(?<goodbye>#{GOODBYE})|(?<immediate>#{IMMEDIATE_RESP})\r\n)\r\n/i
18
19
 
19
20
  attr_accessor :ami_version
20
21
 
@@ -69,7 +70,7 @@ module RubyAMI
69
70
 
70
71
  msg = if match[:event]
71
72
  Event.new match[:event_name]
72
- elsif match[:success] || match[:pong]
73
+ elsif match[:success] || match[:pong] || match[:goodbye]
73
74
  Response.new
74
75
  elsif match[:follows]
75
76
  response_follows = true
@@ -2,6 +2,10 @@
2
2
  module RubyAMI
3
3
  class Stream
4
4
  class ConnectionStatus
5
+ def name
6
+ self.class.to_s
7
+ end
8
+
5
9
  def eql?(other)
6
10
  other.is_a? self.class
7
11
  end
@@ -37,7 +41,7 @@ module RubyAMI
37
41
  end
38
42
  post_init
39
43
  loop { receive_data @socket.readpartial(4096) }
40
- rescue Errno::ECONNREFUSED, SocketError => e
44
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError => e
41
45
  logger.error "Connection failed due to #{e.class}. Check your config and the server."
42
46
  rescue EOFError
43
47
  logger.info "Client socket closed!"
@@ -57,14 +61,16 @@ module RubyAMI
57
61
  @socket.write data
58
62
  end
59
63
 
60
- def send_action(name, headers = {})
64
+ def send_action(name, headers = {}, error_handler = self.method(:abort))
61
65
  condition = Celluloid::Condition.new
62
66
  action = dispatch_action name, headers do |response|
63
67
  condition.signal response
64
68
  end
65
69
  condition.wait
66
70
  action.response.tap do |resp|
67
- abort resp if resp.is_a? Exception
71
+ if resp.is_a? Exception
72
+ error_handler.call(resp)
73
+ end
68
74
  end
69
75
  end
70
76
 
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module RubyAMI
3
- VERSION = "2.2.1"
3
+ VERSION = "2.3.0"
4
4
  end
@@ -66,7 +66,7 @@ module RubyAMI
66
66
  it 'should shut down the client' do
67
67
  subject.events_stream.terminate
68
68
  sleep 0.2
69
- subject.should_not be_alive
69
+ subject.alive?.should be_false
70
70
  end
71
71
  end
72
72
 
@@ -74,7 +74,7 @@ module RubyAMI
74
74
  it 'should shut down the client' do
75
75
  subject.actions_stream.terminate
76
76
  sleep 0.2
77
- subject.should_not be_alive
77
+ subject.alive?.should be_false
78
78
  end
79
79
  end
80
80
 
@@ -190,20 +190,56 @@ Message: Recording started
190
190
  response.should == Response.new('ActionID' => RubyAMI.new_uuid, 'Message' => 'Recording started')
191
191
  end
192
192
 
193
+ it 'should handle disconnect as a Response' do
194
+ response = nil
195
+ mocked_server(1, lambda { response = @stream.send_action 'Logoff' }) do |val, server|
196
+ server.send_data <<-EVENT
197
+ Response: Goodbye
198
+ ActionID: #{RubyAMI.new_uuid}
199
+ Message: Thanks for all the fish.
200
+
201
+ EVENT
202
+ end
203
+
204
+ response.should == Response.new('ActionID' => RubyAMI.new_uuid, 'Message' => 'Thanks for all the fish.')
205
+ end
206
+
193
207
  describe 'when it is an error' do
194
- it 'should be raised by #send_action, but not kill the stream' do
195
- send_action = lambda do
196
- expect { @stream.send_action 'status' }.to raise_error(RubyAMI::Error, 'Action failed')
197
- @stream.should be_alive
208
+ describe 'when there is no error handler' do
209
+ it 'should be raised by #send_action, but not kill the stream' do
210
+ send_action = lambda do
211
+ expect { @stream.send_action 'status' }.to raise_error(RubyAMI::Error, 'Action failed')
212
+ @stream.should be_alive
213
+ end
214
+
215
+ mocked_server(1, send_action) do |val, server|
216
+ server.send_data <<-EVENT
217
+ Response: Error
218
+ ActionID: #{RubyAMI.new_uuid}
219
+ Message: Action failed
220
+
221
+ EVENT
222
+ end
198
223
  end
224
+ end
199
225
 
200
- mocked_server(1, send_action) do |val, server|
201
- server.send_data <<-EVENT
226
+ describe 'when there is an error handler' do
227
+ it 'should call the error handler' do
228
+ error_handler = lambda { |resp| resp.should be_a_kind_of RubyAMI::Error }
229
+
230
+ send_action = lambda do
231
+ expect { @stream.send_action 'status', {}, error_handler }.to_not raise_error
232
+ @stream.should be_alive
233
+ end
234
+
235
+ mocked_server(1, send_action) do |val, server|
236
+ server.send_data <<-EVENT
202
237
  Response: Error
203
238
  ActionID: #{RubyAMI.new_uuid}
204
239
  Message: Action failed
205
240
 
206
- EVENT
241
+ EVENT
242
+ end
207
243
  end
208
244
  end
209
245
  end
@@ -257,4 +293,12 @@ ActionID: #{RubyAMI.new_uuid}
257
293
  @stream.alive?.should be false
258
294
  end
259
295
  end
296
+
297
+ describe Stream::Connected do
298
+ its(:name) { should == 'RubyAMI::Stream::Connected' }
299
+ end
300
+
301
+ describe Stream::Disconnected do
302
+ its(:name) { should == 'RubyAMI::Stream::Disconnected' }
303
+ end
260
304
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_ami
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
5
- prerelease:
4
+ version: 2.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ben Langfeld
@@ -10,182 +9,160 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2014-05-22 00:00:00.000000000 Z
12
+ date: 2015-06-03 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: celluloid-io
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ~>
18
+ - - "~>"
21
19
  - !ruby/object:Gem::Version
22
20
  version: '0.13'
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ~>
25
+ - - "~>"
29
26
  - !ruby/object:Gem::Version
30
27
  version: '0.13'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: bundler
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ~>
32
+ - - "~>"
37
33
  - !ruby/object:Gem::Version
38
34
  version: '1.0'
39
35
  type: :development
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ~>
39
+ - - "~>"
45
40
  - !ruby/object:Gem::Version
46
41
  version: '1.0'
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: rspec
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
- - - ~>
46
+ - - "~>"
53
47
  - !ruby/object:Gem::Version
54
48
  version: '2.5'
55
49
  type: :development
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
- - - ~>
53
+ - - "~>"
61
54
  - !ruby/object:Gem::Version
62
55
  version: '2.5'
63
56
  - !ruby/object:Gem::Dependency
64
57
  name: cucumber
65
58
  requirement: !ruby/object:Gem::Requirement
66
- none: false
67
59
  requirements:
68
- - - ! '>='
60
+ - - ">="
69
61
  - !ruby/object:Gem::Version
70
62
  version: '0'
71
63
  type: :development
72
64
  prerelease: false
73
65
  version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
66
  requirements:
76
- - - ! '>='
67
+ - - ">="
77
68
  - !ruby/object:Gem::Version
78
69
  version: '0'
79
70
  - !ruby/object:Gem::Dependency
80
71
  name: yard
81
72
  requirement: !ruby/object:Gem::Requirement
82
- none: false
83
73
  requirements:
84
- - - ~>
74
+ - - "~>"
85
75
  - !ruby/object:Gem::Version
86
76
  version: '0.6'
87
77
  type: :development
88
78
  prerelease: false
89
79
  version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
80
  requirements:
92
- - - ~>
81
+ - - "~>"
93
82
  - !ruby/object:Gem::Version
94
83
  version: '0.6'
95
84
  - !ruby/object:Gem::Dependency
96
85
  name: rake
97
86
  requirement: !ruby/object:Gem::Requirement
98
- none: false
99
87
  requirements:
100
- - - ! '>='
88
+ - - ">="
101
89
  - !ruby/object:Gem::Version
102
90
  version: '0'
103
91
  type: :development
104
92
  prerelease: false
105
93
  version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
94
  requirements:
108
- - - ! '>='
95
+ - - ">="
109
96
  - !ruby/object:Gem::Version
110
97
  version: '0'
111
98
  - !ruby/object:Gem::Dependency
112
99
  name: guard-rspec
113
100
  requirement: !ruby/object:Gem::Requirement
114
- none: false
115
101
  requirements:
116
- - - ! '>='
102
+ - - ">="
117
103
  - !ruby/object:Gem::Version
118
104
  version: '0'
119
105
  type: :development
120
106
  prerelease: false
121
107
  version_requirements: !ruby/object:Gem::Requirement
122
- none: false
123
108
  requirements:
124
- - - ! '>='
109
+ - - ">="
125
110
  - !ruby/object:Gem::Version
126
111
  version: '0'
127
112
  - !ruby/object:Gem::Dependency
128
113
  name: guard-shell
129
114
  requirement: !ruby/object:Gem::Requirement
130
- none: false
131
115
  requirements:
132
- - - ! '>='
116
+ - - ">="
133
117
  - !ruby/object:Gem::Version
134
118
  version: '0'
135
119
  type: :development
136
120
  prerelease: false
137
121
  version_requirements: !ruby/object:Gem::Requirement
138
- none: false
139
122
  requirements:
140
- - - ! '>='
123
+ - - ">="
141
124
  - !ruby/object:Gem::Version
142
125
  version: '0'
143
126
  - !ruby/object:Gem::Dependency
144
127
  name: guard-cucumber
145
128
  requirement: !ruby/object:Gem::Requirement
146
- none: false
147
129
  requirements:
148
- - - ! '>='
130
+ - - ">="
149
131
  - !ruby/object:Gem::Version
150
132
  version: '0'
151
133
  type: :development
152
134
  prerelease: false
153
135
  version_requirements: !ruby/object:Gem::Requirement
154
- none: false
155
136
  requirements:
156
- - - ! '>='
137
+ - - ">="
157
138
  - !ruby/object:Gem::Version
158
139
  version: '0'
159
140
  - !ruby/object:Gem::Dependency
160
141
  name: guard-rake
161
142
  requirement: !ruby/object:Gem::Requirement
162
- none: false
163
143
  requirements:
164
- - - ! '>='
144
+ - - ">="
165
145
  - !ruby/object:Gem::Version
166
146
  version: '0'
167
147
  type: :development
168
148
  prerelease: false
169
149
  version_requirements: !ruby/object:Gem::Requirement
170
- none: false
171
150
  requirements:
172
- - - ! '>='
151
+ - - ">="
173
152
  - !ruby/object:Gem::Version
174
153
  version: '0'
175
154
  - !ruby/object:Gem::Dependency
176
155
  name: benchmark_suite
177
156
  requirement: !ruby/object:Gem::Requirement
178
- none: false
179
157
  requirements:
180
- - - ! '>='
158
+ - - ">="
181
159
  - !ruby/object:Gem::Version
182
160
  version: '0'
183
161
  type: :development
184
162
  prerelease: false
185
163
  version_requirements: !ruby/object:Gem::Requirement
186
- none: false
187
164
  requirements:
188
- - - ! '>='
165
+ - - ">="
189
166
  - !ruby/object:Gem::Version
190
167
  version: '0'
191
168
  description: A Ruby client library for the Asterisk Management Interface built on
@@ -197,9 +174,9 @@ executables: []
197
174
  extensions: []
198
175
  extra_rdoc_files: []
199
176
  files:
200
- - .gitignore
201
- - .rspec
202
- - .travis.yml
177
+ - ".gitignore"
178
+ - ".rspec"
179
+ - ".travis.yml"
203
180
  - CHANGELOG.md
204
181
  - Gemfile
205
182
  - Guardfile
@@ -240,27 +217,26 @@ files:
240
217
  - spec/support/mock_server.rb
241
218
  homepage: ''
242
219
  licenses: []
220
+ metadata: {}
243
221
  post_install_message:
244
222
  rdoc_options: []
245
223
  require_paths:
246
224
  - lib
247
225
  required_ruby_version: !ruby/object:Gem::Requirement
248
- none: false
249
226
  requirements:
250
- - - ! '>='
227
+ - - ">="
251
228
  - !ruby/object:Gem::Version
252
229
  version: '0'
253
230
  required_rubygems_version: !ruby/object:Gem::Requirement
254
- none: false
255
231
  requirements:
256
- - - ! '>='
232
+ - - ">="
257
233
  - !ruby/object:Gem::Version
258
234
  version: '0'
259
235
  requirements: []
260
236
  rubyforge_project: ruby_ami
261
- rubygems_version: 1.8.23
237
+ rubygems_version: 2.4.5
262
238
  signing_key:
263
- specification_version: 3
239
+ specification_version: 4
264
240
  summary: Futzing with AMI so you don't have to
265
241
  test_files:
266
242
  - features/lexer.feature