ruby_ami 2.4.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 78ab0e1cb98c4b9cc7937dce36985dd5f928f3b6
4
- data.tar.gz: b933392977d95722eacbe58881d6a61848f9652c
3
+ metadata.gz: d8f5b78e09b9c102fe10006cafb1a8fad7af27bd
4
+ data.tar.gz: d6b02c5e8bc1721cbd0666df628e0f7f5c3d1bef
5
5
  SHA512:
6
- metadata.gz: 4e9e1e68b4c7526f2c0943575285f95c19dd8a466d53b514115a524eb2d38806bea6bf962d6a169fc734be01e5d564b00ae1c5a9fdd7bee5e5a8107cfb8a100e
7
- data.tar.gz: 98128f68562f0971c1b6912b52626fbe5bc6b6ed930dd7c6365640cf515b3ec8337f3eb1478e7e4018b8a7bac95eafda388eb56fe306262dc87f5a5161b29be0
6
+ metadata.gz: 5a544ce205149a415df2cbbcf0b51e6c01f4980f6fe711a23bbe3831c4530a494c1846b756b0406a9ea0f365b180325168e759751b7eedbfea3b398276bd2c8e
7
+ data.tar.gz: f292c56da86738c9a6e71e14db5fe6374b2b9f56d1d290a566107ed424baae4fed3d3017026a2b35ab315dea9fbb2c9e9b74e3c60b0a8e8b036a6d2e840bea76
@@ -1,15 +1,12 @@
1
1
  language: ruby
2
2
  sudo: false
3
3
  rvm:
4
- - 1.9.3
5
- - 2.0.0
6
- - 2.1.0
7
- - jruby
8
- - rbx-2.1.1
4
+ - 2.2.5
5
+ - 2.3.1
6
+ - jruby-9.1.2.0
9
7
  - ruby-head
10
8
  matrix:
11
9
  allow_failures:
12
10
  - rvm: ruby-head
13
- - rvm: rbx-2.1.1
14
11
  notifications:
15
12
  irc: "irc.freenode.org#adhearsion"
@@ -1,5 +1,11 @@
1
1
  # [develop](https://github.com/adhearsion/ruby_ami)
2
2
 
3
+ # [3.0.0](https://github.com/adhearsion/ruby_ami/compare/v2.4.0...v3.0.0) - [2016-07-25](https://rubygems.org/gems/ruby_ami/versions/3.0.0)
4
+ * Breaking change: Ruby 1.9 is no longer supported. Minimum supported versions are Ruby 2.2.0 and JRuby 9.0.0.0
5
+ * Breaking change: Removed the deprecated `RubyAMI::Client` because it is no longer relevant.
6
+ * Breaking change: Start the connection when the `RubyAMI::Stream` starts, permitting supervised restart of the stream on connection failure. To support this, the event callback now passes a second parameter which is the stream itself.
7
+ * Feature: Optimisation of the protocol lexer
8
+
3
9
  # [2.4.0](https://github.com/adhearsion/ruby_ami/compare/v2.3.0...v2.4.0) - [2015-12-07](https://rubygems.org/gems/ruby_ami/versions/2.4.0)
4
10
  # Feature: Reveal the AMI version for a `Stream` via `Stream#version`
5
11
 
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Ben Langfeld, Jay Phillips
1
+ Copyright (c) 2011-2016 Ben Langfeld, Jay Phillips
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Coverage Status](https://coveralls.io/repos/adhearsion/ruby_ami/badge.png?branch=develop)](https://coveralls.io/r/adhearsion/ruby_ami)
8
8
  [![Inline docs](http://inch-ci.org/github/adhearsion/ruby_ami.png?branch=develop)](http://inch-ci.org/github/adhearsion/ruby_ami)
9
9
 
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.
10
+ RubyAMI is an AMI client library in Ruby based on Celluloid 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.
11
11
 
12
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.
13
13
 
@@ -21,10 +21,6 @@ In order to setup a connection to listen for AMI events, one can do:
21
21
  ```ruby
22
22
  require 'ruby_ami'
23
23
 
24
- stream = RubyAMI::Stream.new '127.0.0.1', 5038, 'manager', 'password',
25
- ->(e) { handle_event e },
26
- Logger.new(STDOUT), 10
27
-
28
24
  def handle_event(event)
29
25
  case event.name
30
26
  when 'FullyBooted'
@@ -34,7 +30,19 @@ def handle_event(event)
34
30
  end
35
31
  end
36
32
 
37
- $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.
33
+ stream = RubyAMI::Stream.new '127.0.0.1', 5038, 'manager', 'password',
34
+ ->(e, stream) { handle_event e },
35
+ Logger.new(STDOUT), 10
36
+
37
+ Celluloid::Actor.join(stream) # This will block until the actor is terminated elsewhere. Otherwise, the actor will run in its own thread allowing other work to be done here.
38
+ ```
39
+
40
+ Note that using `Stream.new`, the actor will shut down when the connection is lost (and in this case the program will exit). If it is necessary to restart the actor on failure, you can start it in a Celluloid supervisor:
41
+
42
+ ```ruby
43
+ RubyAMI::Stream.supervise_as :ami_connection, '127.0.0.1', 5038, 'manager', 'password',
44
+ ->(e, stream) { handle_event e },
45
+ Logger.new(STDOUT), 10
38
46
  ```
39
47
 
40
48
  It is also possible to execute actions in response to events:
@@ -42,26 +50,24 @@ It is also possible to execute actions in response to events:
42
50
  ```ruby
43
51
  require 'ruby_ami'
44
52
 
45
- $stream = RubyAMI::Stream.new '127.0.0.1', 5038, 'manager', 'password',
46
- ->(e) { handle_event e },
47
- Logger.new(STDOUT), 10
48
-
49
- def handle_event(event)
53
+ def handle_event(event, stream)
50
54
  case event.name
51
55
  when 'FullyBooted'
52
56
  puts "The connection was successful. Originating a call."
53
- response = $stream.send_action 'Originate', 'Channel' => 'SIP/foo'
57
+ response = stream.send_action 'Originate', 'Channel' => 'SIP/foo'
54
58
  puts "The call origination resulted in #{response.inspect}"
55
59
  end
56
60
  end
57
61
 
58
- $stream.run
62
+ stream = RubyAMI::Stream.new '127.0.0.1', 5038, 'manager', 'password',
63
+ ->(e, stream) { handle_event e, stream },
64
+ Logger.new(STDOUT), 10
65
+
66
+ Celluloid::Actor.join(stream) # This will block until the actor is terminated elsewhere. Otherwise, the actor will run in its own thread allowing other work to be done here.
59
67
  ```
60
68
 
61
69
  Executing actions does not strictly have to be done within the event handler, but it is not valid to send AMI events before receiving a `FullyBooted` event. If you attempt to execute an action prior to this, it may fail, and `RubyAMI::Stream` will not help you recover or queue the action until the connection is `FullyBooted`; you must manage this timing yourself. That said, assuming you take care of this, you may invoke `RubyAMI::Stream#send_action` from anywhere in your code and it will return the response of the action.
62
70
 
63
- 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**.
64
-
65
71
  ## Links:
66
72
  * [Source](https://github.com/adhearsion/ruby_ami)
67
73
  * [Documentation](http://rdoc.info/github/adhearsion/ruby_ami/master/frames)
@@ -78,4 +84,4 @@ RubyAMI also has a class called `RubyAMI::Client` which used to be the main usag
78
84
 
79
85
  ## Copyright
80
86
 
81
- Copyright (c) 2013 Ben Langfeld, Jay Phillips. MIT licence (see LICENSE for details).
87
+ Copyright (c) 2011-2016 Ben Langfeld, Jay Phillips. MIT licence (see LICENSE for details).
@@ -17,7 +17,6 @@ end
17
17
  action
18
18
  agi_result_parser
19
19
  async_agi_environment_parser
20
- client
21
20
  error
22
21
  event
23
22
  lexer
@@ -16,6 +16,11 @@ module RubyAMI
16
16
  @headers[key] = value
17
17
  end
18
18
 
19
+ def merge_headers!(hash)
20
+ self.message = hash['Message'] if hash.has_key?('Message')
21
+ @headers.merge!(hash)
22
+ end
23
+
19
24
  def action_id
20
25
  @headers['ActionID']
21
26
  end
@@ -88,9 +88,9 @@ module RubyAMI
88
88
 
89
89
  # Strip off the header line
90
90
  raw.slice! HEADER_SLICE
91
- populate_message_body msg, raw
91
+ raw_index = populate_message_body msg, raw
92
92
 
93
- return msg if response_follows && !handle_response_follows(msg, raw)
93
+ return msg if response_follows && !handle_response_follows(msg, raw[raw_index..-1])
94
94
 
95
95
  case msg
96
96
  when Error
@@ -129,11 +129,15 @@ module RubyAMI
129
129
  @delegate.syntax_error_encountered ignored_chunk
130
130
  end
131
131
 
132
+ # returns first char index after last match
132
133
  def populate_message_body(obj, raw)
133
- while raw.slice! KEYVALUEPAIR
134
- obj[$1] = $2
134
+ headers = raw.scan(KEYVALUEPAIR)
135
+ if match = $~
136
+ obj.merge_headers!(Hash[headers])
137
+ match.end(match.size - 1) + 2
138
+ else
139
+ 0
135
140
  end
136
- obj
137
141
  end
138
142
 
139
143
  def handle_response_follows(obj, raw)
@@ -28,6 +28,10 @@ module RubyAMI
28
28
  @headers.clone
29
29
  end
30
30
 
31
+ def merge_headers!(hash)
32
+ @headers.merge!(hash)
33
+ end
34
+
31
35
  def [](arg)
32
36
  @headers[arg.to_s]
33
37
  end
@@ -29,6 +29,7 @@ module RubyAMI
29
29
  @lexer = Lexer.new self
30
30
  @sent_actions = {}
31
31
  @causal_actions = {}
32
+ async.run
32
33
  end
33
34
 
34
35
  [:started, :stopped, :ready].each do |state|
@@ -125,7 +126,7 @@ module RubyAMI
125
126
  end
126
127
 
127
128
  def fire_event(event)
128
- @event_callback.call event
129
+ @event_callback.call event, current_actor
129
130
  end
130
131
 
131
132
  def register_sent_action(action)
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module RubyAMI
3
- VERSION = "2.4.0"
3
+ VERSION = "3.0.0"
4
4
  end
@@ -13,12 +13,15 @@ Gem::Specification.new do |s|
13
13
 
14
14
  s.rubyforge_project = "ruby_ami"
15
15
 
16
+ s.required_ruby_version = '>= 2.2.0'
17
+
16
18
  s.files = `git ls-files`.split("\n") << 'lib/ruby_ami/lexer.rb'
17
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
21
  s.require_paths = ["lib"]
20
22
 
21
23
  s.add_runtime_dependency %q<celluloid-io>, ["~> 0.13"]
24
+ s.add_runtime_dependency %q<celluloid>, ["~> 0.16.0"]
22
25
 
23
26
  s.add_development_dependency %q<bundler>, ["~> 1.0"]
24
27
  s.add_development_dependency %q<rspec>, ["~> 2.5"]
@@ -15,13 +15,15 @@ module RubyAMI
15
15
  it { should_not be_complete }
16
16
 
17
17
  describe "SIPPeers actions" do
18
- subject { Action.new('SIPPeers') }
19
- its(:has_causal_events?) { should be true }
18
+ it "has causal events" do
19
+ Action.new('SIPPeers').has_causal_events?.should be true
20
+ end
20
21
  end
21
22
 
22
23
  describe "the ParkedCalls terminator event" do
23
- subject { Action.new('ParkedCalls') }
24
- its(:causal_event_terminator_name) { should == "parkedcallscomplete" }
24
+ it "knows its causal event terminator name" do
25
+ Action.new('ParkedCalls').causal_event_terminator_name.should == "parkedcallscomplete"
26
+ end
25
27
  end
26
28
 
27
29
  it "should properly convert itself into a String when additional headers are given" do
@@ -108,7 +110,7 @@ module RubyAMI
108
110
 
109
111
  it { should be_complete }
110
112
 
111
- its(:response) { should be response }
113
+ it { subject.response.should be response }
112
114
  end
113
115
  end
114
116
  end
@@ -16,46 +16,46 @@ module RubyAMI
16
16
  context 'with a simple result with no data' do
17
17
  let(:result_string) { "200%20result=123%0A" }
18
18
 
19
- its(:code) { should == 200 }
20
- its(:result) { should == 123 }
21
- its(:data) { should == '' }
22
- its(:data_hash) { should == nil }
19
+ it { subject.code.should == 200 }
20
+ it { subject.result.should == 123 }
21
+ it { subject.data.should == '' }
22
+ it { subject.data_hash.should == nil }
23
23
  end
24
24
 
25
25
  context 'with a simple unescaped result with no data' do
26
26
  let(:result_string) { "200 result=123" }
27
27
 
28
- its(:code) { should == 200 }
29
- its(:result) { should == 123 }
30
- its(:data) { should == '' }
31
- its(:data_hash) { should == nil }
28
+ it { subject.code.should == 200 }
29
+ it { subject.result.should == 123 }
30
+ it { subject.data.should == '' }
31
+ it { subject.data_hash.should == nil }
32
32
  end
33
33
 
34
34
  context 'with a result and data in parens' do
35
35
  let(:result_string) { "200%20result=-123%20(timeout)%0A" }
36
36
 
37
- its(:code) { should == 200 }
38
- its(:result) { should == -123 }
39
- its(:data) { should == 'timeout' }
40
- its(:data_hash) { should == nil }
37
+ it { subject.code.should == 200 }
38
+ it { subject.result.should == -123 }
39
+ it { subject.data.should == 'timeout' }
40
+ it { subject.data_hash.should == nil }
41
41
  end
42
42
 
43
43
  context 'with a result and key-value data' do
44
44
  let(:result_string) { "200%20result=123%20foo=bar%0A" }
45
45
 
46
- its(:code) { should == 200 }
47
- its(:result) { should == 123 }
48
- its(:data) { should == 'foo=bar' }
49
- its(:data_hash) { should == {'foo' => 'bar'} }
46
+ it { subject.code.should == 200 }
47
+ it { subject.result.should == 123 }
48
+ it { subject.data.should == 'foo=bar' }
49
+ it { subject.data_hash.should == {'foo' => 'bar'} }
50
50
  end
51
51
 
52
52
  context 'with a 5xx error' do
53
53
  let(:result_string) { "510%20Invalid%20or%20unknown%20command%0A" }
54
54
 
55
- its(:code) { should == 510 }
56
- its(:result) { should be_nil }
57
- its(:data) { should == 'Invalid or unknown command' }
58
- its(:data_hash) { should be_nil }
55
+ it { subject.code.should == 510 }
56
+ it { subject.result.should be_nil }
57
+ it { subject.data.should == 'Invalid or unknown command' }
58
+ it { subject.data_hash.should be_nil }
59
59
  end
60
60
  end
61
61
  end
@@ -9,12 +9,12 @@ module RubyAMI
9
9
 
10
10
  subject { described_class.new environment_string }
11
11
 
12
- its(:to_s) { should == environment_string }
13
- its(:to_s) { should_not be environment_string }
12
+ it { subject.to_s.should == environment_string }
13
+ it { subject.to_s.should_not be environment_string }
14
14
 
15
15
  describe 'retrieving a hash representation' do
16
- its(:to_hash) do
17
- should == {
16
+ it "should return a hash of attributes" do
17
+ subject.to_hash.should == {
18
18
  :agi_request => 'async',
19
19
  :agi_channel => 'SIP/1234-00000000',
20
20
  :agi_language => 'en',
@@ -3,6 +3,6 @@ require 'spec_helper'
3
3
 
4
4
  module RubyAMI
5
5
  describe Error do
6
- pending
6
+ skip
7
7
  end # Error
8
8
  end # RubyAMI
@@ -6,13 +6,13 @@ module RubyAMI
6
6
  let(:server_port) { 50000 - rand(1000) }
7
7
 
8
8
  def client
9
- @client ||= mock('Client')
9
+ @client ||= double('Client')
10
10
  end
11
11
 
12
12
  before do
13
- def client.message_received(message)
13
+ def client.message_received(message, stream)
14
14
  @messages ||= Queue.new
15
- @messages << message
15
+ @messages << [message, stream]
16
16
  end
17
17
 
18
18
  def client.messages
@@ -31,37 +31,29 @@ module RubyAMI
31
31
 
32
32
  def mocked_server(times = nil, fake_client = nil, &block)
33
33
  mock_target = MockServer.new
34
- mock_target.should_receive(:receive_data).send(*(times ? [:exactly, times] : [:at_least, 1])).with &block
34
+ mock_target.should_receive(:receive_data).send(*(times ? [:exactly, times] : [:at_least, 1]), &block)
35
35
  s = ServerMock.new '127.0.0.1', server_port, mock_target
36
- @stream = Stream.new '127.0.0.1', server_port, username, password, lambda { |m| client.message_received m }
37
- @stream.async.run
36
+ @stream = Stream.new '127.0.0.1', server_port, username, password, lambda { |m, stream| client.message_received m, stream }
38
37
  fake_client.call if fake_client.respond_to? :call
39
- Celluloid::Actor.join s
40
38
  Timeout.timeout 5 do
39
+ Celluloid::Actor.join s
41
40
  Celluloid::Actor.join @stream
42
41
  end
43
- end
44
-
45
- def expect_connected_event
46
- client.should_receive(:message_received).with Stream::Connected.new
47
- end
48
-
49
- def expect_disconnected_event
50
- client.should_receive(:message_received).with Stream::Disconnected.new
42
+ rescue Timeout::Error
51
43
  end
52
44
 
53
45
  before { @sequence = 1 }
54
46
 
55
47
  describe "after connection" do
56
48
  it "should be started" do
57
- expect_connected_event
58
- expect_disconnected_event
59
- mocked_server 0, -> { @stream.started?.should be_true }
49
+ mocked_server 0, -> { @stream.started?.should be true }
50
+ client_messages.should be == [
51
+ [Stream::Connected.new, @stream],
52
+ [Stream::Disconnected.new, @stream],
53
+ ]
60
54
  end
61
55
 
62
56
  it "stores the reported AMI version" do
63
- expect_connected_event
64
- expect_disconnected_event
65
57
  mocked_server(1, lambda {
66
58
  @stream.send_action('Command') # Just to get the server kicked in to replying using the below block
67
59
  expect(@stream.version).to eq('2.8.0')
@@ -79,8 +71,6 @@ Message: Recording started
79
71
  end
80
72
 
81
73
  it "can send an action" do
82
- expect_connected_event
83
- expect_disconnected_event
84
74
  mocked_server(1, lambda { @stream.send_action('Command') }) do |val, server|
85
75
  val.should == <<-ACTION
86
76
  Action: command\r
@@ -98,8 +88,6 @@ Message: Recording started
98
88
  end
99
89
 
100
90
  it "can send an action with headers" do
101
- expect_connected_event
102
- expect_disconnected_event
103
91
  mocked_server(1, lambda { @stream.send_action('Command', 'Command' => 'RECORD FILE evil') }) do |val, server|
104
92
  val.should == <<-ACTION
105
93
  Action: command\r
@@ -148,8 +136,6 @@ Extension '1,1,AGI(agi:async)' added into 'adhearsion-redirect' context
148
136
  let(:password) { 'jones' }
149
137
 
150
138
  it "should log itself in" do
151
- expect_connected_event
152
- expect_disconnected_event
153
139
  mocked_server(1, lambda { }) do |val, server|
154
140
  val.should == <<-ACTION
155
141
  Action: login\r
@@ -183,18 +169,13 @@ Cause: 0
183
169
  end
184
170
 
185
171
  client_messages.should be == [
186
- Stream::Connected.new,
187
- Event.new('Hangup', 'Channel' => 'SIP/101-3f3f', 'Uniqueid' => '1094154427.10', 'Cause' => '0'),
188
- Stream::Disconnected.new
172
+ [Stream::Connected.new, @stream],
173
+ [Event.new('Hangup', 'Channel' => 'SIP/101-3f3f', 'Uniqueid' => '1094154427.10', 'Cause' => '0'), @stream],
174
+ [Stream::Disconnected.new, @stream],
189
175
  ]
190
176
  end
191
177
 
192
178
  describe 'when a response is received' do
193
- before do
194
- expect_connected_event
195
- expect_disconnected_event
196
- end
197
-
198
179
  it 'should be returned from #send_action' do
199
180
  response = nil
200
181
  mocked_server(1, lambda { response = @stream.send_action 'Command', 'Command' => 'RECORD FILE evil' }) do |val, server|
@@ -219,7 +200,7 @@ Message: Thanks for all the fish.
219
200
 
220
201
  EVENT
221
202
  end
222
-
203
+
223
204
  response.should == Response.new('ActionID' => RubyAMI.new_uuid, 'Message' => 'Thanks for all the fish.')
224
205
  end
225
206
 
@@ -304,20 +285,26 @@ ActionID: #{RubyAMI.new_uuid}
304
285
  end
305
286
 
306
287
  it 'puts itself in the stopped state and fires a disconnected event when unbound' do
307
- expect_connected_event
308
- expect_disconnected_event
309
288
  mocked_server(1, lambda { @stream.send_data 'Foo' }) do |val, server|
310
289
  @stream.stopped?.should be false
311
290
  end
312
291
  @stream.alive?.should be false
292
+ client_messages.should be == [
293
+ [Stream::Connected.new, @stream],
294
+ [Stream::Disconnected.new, @stream],
295
+ ]
313
296
  end
314
297
  end
315
298
 
316
299
  describe Stream::Connected do
317
- its(:name) { should == 'RubyAMI::Stream::Connected' }
300
+ it "has a name matching the class" do
301
+ subject.name.should == 'RubyAMI::Stream::Connected'
302
+ end
318
303
  end
319
304
 
320
305
  describe Stream::Disconnected do
321
- its(:name) { should == 'RubyAMI::Stream::Disconnected' }
306
+ it "has a name matching the class" do
307
+ subject.name.should == 'RubyAMI::Stream::Disconnected'
308
+ end
322
309
  end
323
310
  end
@@ -10,6 +10,7 @@ RSpec.configure do |config|
10
10
  config.mock_with :rspec
11
11
  config.filter_run :focus => true
12
12
  config.run_all_when_everything_filtered = true
13
+ config.raise_errors_for_deprecations!
13
14
 
14
15
  config.before :each do
15
16
  uuid = RubyAMI.new_uuid
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_ami
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Langfeld
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-12-07 00:00:00.000000000 Z
12
+ date: 2016-07-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: celluloid-io
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0.13'
28
+ - !ruby/object:Gem::Dependency
29
+ name: celluloid
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.16.0
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 0.16.0
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: bundler
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -196,7 +210,6 @@ files:
196
210
  - lib/ruby_ami/action.rb
197
211
  - lib/ruby_ami/agi_result_parser.rb
198
212
  - lib/ruby_ami/async_agi_environment_parser.rb
199
- - lib/ruby_ami/client.rb
200
213
  - lib/ruby_ami/core_ext/celluloid.rb
201
214
  - lib/ruby_ami/error.rb
202
215
  - lib/ruby_ami/event.rb
@@ -208,7 +221,6 @@ files:
208
221
  - spec/ruby_ami/action_spec.rb
209
222
  - spec/ruby_ami/agi_result_parser_spec.rb
210
223
  - spec/ruby_ami/async_agi_environment_parser_spec.rb
211
- - spec/ruby_ami/client_spec.rb
212
224
  - spec/ruby_ami/error_spec.rb
213
225
  - spec/ruby_ami/event_spec.rb
214
226
  - spec/ruby_ami/response_spec.rb
@@ -226,7 +238,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
226
238
  requirements:
227
239
  - - ">="
228
240
  - !ruby/object:Gem::Version
229
- version: '0'
241
+ version: 2.2.0
230
242
  required_rubygems_version: !ruby/object:Gem::Requirement
231
243
  requirements:
232
244
  - - ">="
@@ -234,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
234
246
  version: '0'
235
247
  requirements: []
236
248
  rubyforge_project: ruby_ami
237
- rubygems_version: 2.4.5
249
+ rubygems_version: 2.5.1
238
250
  signing_key:
239
251
  specification_version: 4
240
252
  summary: Futzing with AMI so you don't have to
@@ -248,11 +260,9 @@ test_files:
248
260
  - spec/ruby_ami/action_spec.rb
249
261
  - spec/ruby_ami/agi_result_parser_spec.rb
250
262
  - spec/ruby_ami/async_agi_environment_parser_spec.rb
251
- - spec/ruby_ami/client_spec.rb
252
263
  - spec/ruby_ami/error_spec.rb
253
264
  - spec/ruby_ami/event_spec.rb
254
265
  - spec/ruby_ami/response_spec.rb
255
266
  - spec/ruby_ami/stream_spec.rb
256
267
  - spec/spec_helper.rb
257
268
  - spec/support/mock_server.rb
258
- has_rdoc:
@@ -1,77 +0,0 @@
1
- # encoding: utf-8
2
- module RubyAMI
3
- class Client
4
- include Celluloid
5
-
6
- trap_exit :stream_died
7
-
8
- attr_reader :events_stream, :actions_stream
9
-
10
- def initialize(options)
11
- @options = options
12
- @event_handler = @options[:event_handler]
13
- @state = :stopped
14
- client = current_actor
15
- @events_stream = new_stream ->(event) { client.async.handle_event event }
16
- @actions_stream = new_stream ->(message) { client.async.handle_message message }
17
- end
18
-
19
- [:started, :stopped, :ready].each do |state|
20
- define_method("#{state}?") { @state == state }
21
- end
22
-
23
- def start
24
- @events_stream.async.run
25
- @actions_stream.async.run
26
- @state = :started
27
- end
28
-
29
- def send_action(*args)
30
- actions_stream.send_action *args
31
- end
32
-
33
- def handle_message(message)
34
- logger.trace "[RECV-ACTIONS]: #{message.inspect}"
35
- case message
36
- when Stream::Connected
37
- send_action 'Events', 'EventMask' => 'Off'
38
- when Stream::Disconnected
39
- when Event
40
- pass_event message
41
- end
42
- end
43
-
44
- def handle_event(event)
45
- logger.trace "[RECV-EVENTS]: #{event.inspect}"
46
- case event
47
- when Stream::Connected, Stream::Disconnected
48
- else
49
- pass_event event
50
- end
51
- end
52
-
53
- private
54
-
55
- def pass_event(event)
56
- @event_handler.call event if @event_handler.respond_to? :call
57
- end
58
-
59
- def new_stream(callback)
60
- Stream.new_link @options[:host], @options[:port], @options[:username], @options[:password], callback, logger, @options[:timeout]
61
- end
62
-
63
- def stream_died(stream, reason = nil)
64
- terminate
65
- end
66
-
67
- def logger
68
- super
69
- rescue
70
- @logger ||= begin
71
- logger = Logger
72
- logger.define_singleton_method :trace, logger.method(:debug)
73
- logger
74
- end
75
- end
76
- end
77
- end
@@ -1,90 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
-
4
- module RubyAMI
5
- describe Client do
6
- let(:event_handler) { [] }
7
-
8
- let(:options) do
9
- {
10
- :host => '127.0.0.1',
11
- :port => 50000 - rand(1000),
12
- :username => 'username',
13
- :password => 'password',
14
- :event_handler => lambda { |event| event_handler << event }
15
- }
16
- end
17
-
18
- subject { Client.new options }
19
-
20
- it { should be_stopped }
21
-
22
- its(:events_stream) { should be_a Stream }
23
- its(:actions_stream) { should be_a Stream }
24
-
25
- it 'should return when the timeout option is specified and reached' do
26
- pending
27
- options[:timeout] = 2
28
- options[:host] = '192.0.2.1' # unreachable IP that will generally cause a timeout (RFC 5737)
29
-
30
- start_time = Time.now
31
- subject.start
32
- duration = Time.now - start_time
33
-
34
- duration.should be_between(options[:timeout], options[:timeout] + 1)
35
- end
36
-
37
- describe 'starting up' do
38
- before do
39
- ms = MockServer.new
40
- ms.should_receive(:receive_data).at_least :once
41
- s = ServerMock.new options[:host], options[:port], ms
42
- subject.async.start
43
- sleep 0.2
44
- end
45
-
46
- it { should be_started }
47
- end
48
-
49
- describe 'logging in streams' do
50
- context 'when the actions stream connects' do
51
- let(:mock_actions_stream) { mock 'Actions Stream' }
52
-
53
- before do
54
- subject.wrapped_object.stub(:actions_stream).and_return mock_actions_stream
55
- end
56
-
57
- it 'should disable events' do
58
- mock_actions_stream.should_receive(:send_action).with 'Events', 'EventMask' => 'Off'
59
-
60
- subject.handle_message Stream::Connected.new
61
- end
62
- end
63
- end
64
-
65
- describe 'when the events stream disconnects' do
66
- it 'should shut down the client' do
67
- subject.events_stream.terminate
68
- sleep 0.2
69
- subject.alive?.should be_false
70
- end
71
- end
72
-
73
- describe 'when the actions stream disconnects' do
74
- it 'should shut down the client' do
75
- subject.actions_stream.terminate
76
- sleep 0.2
77
- subject.alive?.should be_false
78
- end
79
- end
80
-
81
- describe 'when an event is received' do
82
- let(:event) { Event.new 'foobar' }
83
-
84
- it 'should call the event handler' do
85
- subject.handle_event event
86
- event_handler.should == [event]
87
- end
88
- end
89
- end
90
- end