ruby_ami 1.0.1 → 1.1.1
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.
- data/.travis.yml +3 -3
- data/CHANGELOG.md +7 -1
- data/lib/ruby_ami.rb +13 -19
- data/lib/ruby_ami/action.rb +2 -2
- data/lib/ruby_ami/client.rb +14 -14
- data/lib/ruby_ami/error.rb +1 -1
- data/lib/ruby_ami/event.rb +6 -0
- data/lib/ruby_ami/lexer.rl.rb +2 -1
- data/lib/ruby_ami/response.rb +16 -3
- data/lib/ruby_ami/stream.rb +28 -14
- data/lib/ruby_ami/version.rb +1 -1
- data/ruby_ami.gemspec +1 -3
- data/spec/ruby_ami/client_spec.rb +10 -28
- data/spec/ruby_ami/event_spec.rb +67 -1
- data/spec/ruby_ami/response_spec.rb +45 -1
- data/spec/ruby_ami/stream_spec.rb +44 -58
- data/spec/support/mock_server.rb +32 -4
- metadata +10 -43
- data/lib/ruby_ami/Guardfile +0 -6
data/.travis.yml
CHANGED
@@ -3,10 +3,10 @@ rvm:
|
|
3
3
|
- 1.9.2
|
4
4
|
- 1.9.3
|
5
5
|
- jruby-19mode
|
6
|
-
- rbx-19mode
|
6
|
+
# - rbx-19mode
|
7
7
|
- ruby-head
|
8
8
|
before_install:
|
9
|
-
- wget http://ftp.us.debian.org/debian/pool/main/r/ragel/ragel_6.7-1_i386.deb
|
10
|
-
- sudo dpkg -i ragel_6.7-1_i386.deb
|
9
|
+
- wget http://ftp.us.debian.org/debian/pool/main/r/ragel/ragel_6.7-1.1_i386.deb
|
10
|
+
- sudo dpkg -i ragel_6.7-1.1_i386.deb
|
11
11
|
notifications:
|
12
12
|
irc: "irc.freenode.org#adhearsion"
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
# develop
|
1
|
+
# [develop](https://github.com/adhearsion/ruby_ami)
|
2
|
+
|
3
|
+
# [1.1.1](https://github.com/adhearsion/ruby_ami/compare/v1.1.0...v1.1.1) - [2012-06-25](https://rubygems.org/gems/ruby_ami/versions/1.1.1)
|
4
|
+
* v1.1.0 re-released with fixed celluloid-io dependency
|
5
|
+
|
6
|
+
# [1.1.0](https://github.com/adhearsion/ruby_ami/compare/v1.0.1...v1.1.0) - [2012-06-16](https://rubygems.org/gems/ruby_ami/versions/1.1.0)
|
7
|
+
* Change: Switch from EventMachine to Celluloid & CelluloidIO for better JRuby compatability and performance (action and events connections are now in separate threads)
|
2
8
|
|
3
9
|
# 1.0.1 - 2012-04-25
|
4
10
|
* Bugfix: Actions which do not receive a response within 10s will allow further actions to be executed. Synchronous originate has a 60s timeout.
|
data/lib/ruby_ami.rb
CHANGED
@@ -1,18 +1,10 @@
|
|
1
1
|
%w{
|
2
|
-
active_support/dependencies/autoload
|
3
|
-
active_support/core_ext/object/blank
|
4
|
-
active_support/core_ext/numeric/time
|
5
|
-
active_support/core_ext/numeric/bytes
|
6
|
-
active_support/hash_with_indifferent_access
|
7
|
-
|
8
2
|
uuidtools
|
9
|
-
eventmachine
|
10
3
|
future-resource
|
11
4
|
logger
|
12
5
|
girl_friday
|
13
6
|
countdownlatch
|
14
|
-
|
15
|
-
ruby_ami/metaprogramming
|
7
|
+
celluloid/io
|
16
8
|
}.each { |f| require f }
|
17
9
|
|
18
10
|
class Logger
|
@@ -20,14 +12,16 @@ class Logger
|
|
20
12
|
end
|
21
13
|
|
22
14
|
module RubyAMI
|
23
|
-
extend ActiveSupport::Autoload
|
24
|
-
|
25
|
-
autoload :Action
|
26
|
-
autoload :Client
|
27
|
-
autoload :Error
|
28
|
-
autoload :Event
|
29
|
-
autoload :Lexer
|
30
|
-
autoload :Response
|
31
|
-
autoload :Stream
|
32
|
-
autoload :Version
|
33
15
|
end
|
16
|
+
|
17
|
+
%w{
|
18
|
+
action
|
19
|
+
client
|
20
|
+
error
|
21
|
+
event
|
22
|
+
lexer
|
23
|
+
metaprogramming
|
24
|
+
response
|
25
|
+
stream
|
26
|
+
version
|
27
|
+
}.each { |f| require "ruby_ami/#{f}" }
|
data/lib/ruby_ami/action.rb
CHANGED
@@ -9,7 +9,7 @@ module RubyAMI
|
|
9
9
|
|
10
10
|
def initialize(name, headers = {}, &block)
|
11
11
|
@name = name.to_s.downcase.freeze
|
12
|
-
@headers = headers.
|
12
|
+
@headers = headers.freeze
|
13
13
|
@action_id = UUIDTools::UUID.random_create.to_s
|
14
14
|
@response = FutureResource.new
|
15
15
|
@response_callback = block
|
@@ -121,7 +121,7 @@ module RubyAMI
|
|
121
121
|
alias :== :eql?
|
122
122
|
|
123
123
|
def sync_timeout
|
124
|
-
name.downcase == 'originate' && !headers[
|
124
|
+
name.downcase == 'originate' && !headers[:async] ? 60 : 10
|
125
125
|
end
|
126
126
|
|
127
127
|
##
|
data/lib/ruby_ami/client.rb
CHANGED
@@ -41,16 +41,20 @@ module RubyAMI
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def start
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
@state = :started
|
49
|
-
end
|
44
|
+
@events_stream = start_stream lambda { |event| @event_processor << event }
|
45
|
+
@actions_stream = start_stream lambda { |message| @message_processor << message }
|
46
|
+
@state = :started
|
47
|
+
streams.each(&:join)
|
50
48
|
end
|
51
49
|
|
52
50
|
def stop
|
53
|
-
streams.each
|
51
|
+
streams.each do |stream|
|
52
|
+
begin
|
53
|
+
stream.terminate
|
54
|
+
rescue => e
|
55
|
+
logger.error e if logger
|
56
|
+
end
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
def send_action(action, headers = {}, &block)
|
@@ -68,7 +72,7 @@ module RubyAMI
|
|
68
72
|
login_actions
|
69
73
|
when Stream::Disconnected
|
70
74
|
stop_writing_actions
|
71
|
-
|
75
|
+
stop
|
72
76
|
when Event
|
73
77
|
action = @current_action_with_causal_events
|
74
78
|
if action
|
@@ -103,7 +107,7 @@ module RubyAMI
|
|
103
107
|
when Stream::Connected
|
104
108
|
login_events
|
105
109
|
when Stream::Disconnected
|
106
|
-
|
110
|
+
stop
|
107
111
|
else
|
108
112
|
pass_event event
|
109
113
|
end
|
@@ -117,10 +121,6 @@ module RubyAMI
|
|
117
121
|
action
|
118
122
|
end
|
119
123
|
|
120
|
-
def unbind
|
121
|
-
EM.reactor_running? && EM.stop
|
122
|
-
end
|
123
|
-
|
124
124
|
private
|
125
125
|
|
126
126
|
def pass_event(event)
|
@@ -179,7 +179,7 @@ module RubyAMI
|
|
179
179
|
end
|
180
180
|
|
181
181
|
def start_stream(callback)
|
182
|
-
Stream.
|
182
|
+
Stream.new @options[:host], @options[:port], callback
|
183
183
|
end
|
184
184
|
|
185
185
|
def logger
|
data/lib/ruby_ami/error.rb
CHANGED
data/lib/ruby_ami/event.rb
CHANGED
data/lib/ruby_ami/lexer.rl.rb
CHANGED
data/lib/ruby_ami/response.rb
CHANGED
@@ -18,7 +18,7 @@ module RubyAMI
|
|
18
18
|
attr_reader :events
|
19
19
|
|
20
20
|
def initialize
|
21
|
-
@headers =
|
21
|
+
@headers = Hash.new
|
22
22
|
end
|
23
23
|
|
24
24
|
def has_text_body?
|
@@ -30,15 +30,28 @@ module RubyAMI
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def [](arg)
|
33
|
-
@headers[arg]
|
33
|
+
@headers[arg.to_s]
|
34
34
|
end
|
35
35
|
|
36
36
|
def []=(key,value)
|
37
|
-
@headers[key] = value
|
37
|
+
@headers[key.to_s] = value
|
38
38
|
end
|
39
39
|
|
40
40
|
def action_id
|
41
41
|
@headers['ActionID']
|
42
42
|
end
|
43
|
+
|
44
|
+
def inspect
|
45
|
+
"#<#{self.class} #{inspect_attributes.map { |c| "#{c}=#{self.__send__(c).inspect rescue nil}" }.compact * ', '}>"
|
46
|
+
end
|
47
|
+
|
48
|
+
def inspect_attributes
|
49
|
+
[:headers, :text_body, :events, :action]
|
50
|
+
end
|
51
|
+
|
52
|
+
def eql?(o, *fields)
|
53
|
+
o.is_a?(self.class) && (fields + inspect_attributes).all? { |f| self.__send__(f) == o.__send__(f) }
|
54
|
+
end
|
55
|
+
alias :== :eql?
|
43
56
|
end
|
44
57
|
end # RubyAMI
|
data/lib/ruby_ami/stream.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module RubyAMI
|
2
|
-
class Stream
|
2
|
+
class Stream
|
3
3
|
class ConnectionStatus
|
4
4
|
def eql?(other)
|
5
5
|
other.is_a? self.class
|
@@ -11,50 +11,64 @@ module RubyAMI
|
|
11
11
|
Connected = Class.new ConnectionStatus
|
12
12
|
Disconnected = Class.new ConnectionStatus
|
13
13
|
|
14
|
-
|
15
|
-
EM.connect host, port, self, event_callback
|
16
|
-
end
|
14
|
+
include Celluloid::IO
|
17
15
|
|
18
|
-
def initialize(event_callback)
|
16
|
+
def initialize(host, port, event_callback)
|
19
17
|
super()
|
20
18
|
@event_callback = event_callback
|
21
|
-
|
22
|
-
@logger.level = Logger::FATAL
|
23
|
-
@logger.debug "Starting up..."
|
19
|
+
logger.debug "Starting up..."
|
24
20
|
@lexer = Lexer.new self
|
21
|
+
@socket = TCPSocket.from_ruby_socket ::TCPSocket.new(host, port)
|
22
|
+
post_init
|
23
|
+
run!
|
25
24
|
end
|
26
25
|
|
27
26
|
[:started, :stopped, :ready].each do |state|
|
28
27
|
define_method("#{state}?") { @state == state }
|
29
28
|
end
|
30
29
|
|
30
|
+
def run
|
31
|
+
loop { receive_data @socket.readpartial(4096) }
|
32
|
+
rescue EOFError
|
33
|
+
logger.info "Client socket closed!"
|
34
|
+
current_actor.terminate!
|
35
|
+
end
|
36
|
+
|
31
37
|
def post_init
|
32
38
|
@state = :started
|
33
39
|
@event_callback.call Connected.new
|
34
40
|
end
|
35
41
|
|
42
|
+
def send_data(data)
|
43
|
+
@socket.write data
|
44
|
+
end
|
45
|
+
|
36
46
|
def send_action(action)
|
37
|
-
|
47
|
+
logger.debug "[SEND] #{action.to_s}"
|
38
48
|
send_data action.to_s
|
39
49
|
end
|
40
50
|
|
41
51
|
def receive_data(data)
|
42
|
-
|
52
|
+
logger.debug "[RECV] #{data}"
|
43
53
|
@lexer << data
|
44
54
|
end
|
45
55
|
|
46
56
|
def message_received(message)
|
47
|
-
|
57
|
+
logger.debug "[RECV] #{message.inspect}"
|
48
58
|
@event_callback.call message
|
49
59
|
end
|
50
60
|
|
51
61
|
alias :error_received :message_received
|
52
62
|
|
53
|
-
|
54
|
-
|
55
|
-
|
63
|
+
def finalize
|
64
|
+
logger.debug "Finalizing stream"
|
65
|
+
@socket.close if @socket
|
56
66
|
@state = :stopped
|
57
67
|
@event_callback.call Disconnected.new
|
58
68
|
end
|
69
|
+
|
70
|
+
def logger
|
71
|
+
Logger
|
72
|
+
end
|
59
73
|
end
|
60
74
|
end
|
data/lib/ruby_ami/version.rb
CHANGED
data/ruby_ami.gemspec
CHANGED
@@ -18,13 +18,11 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_runtime_dependency %q<activesupport>, ["~> 3.0"]
|
22
21
|
s.add_runtime_dependency %q<uuidtools>, [">= 0"]
|
23
|
-
s.add_runtime_dependency %q<
|
22
|
+
s.add_runtime_dependency %q<celluloid-io>, ["~> 0.11.0"]
|
24
23
|
s.add_runtime_dependency %q<future-resource>, [">= 0"]
|
25
24
|
s.add_runtime_dependency %q<girl_friday>, [">= 0"]
|
26
25
|
s.add_runtime_dependency %q<countdownlatch>, ["~> 1.0"]
|
27
|
-
s.add_runtime_dependency %q<i18n>, [">= 0"]
|
28
26
|
|
29
27
|
s.add_development_dependency %q<bundler>, ["~> 1.0"]
|
30
28
|
s.add_development_dependency %q<rspec>, [">= 2.5.0"]
|
@@ -26,11 +26,11 @@ module RubyAMI
|
|
26
26
|
|
27
27
|
describe 'starting up' do
|
28
28
|
before do
|
29
|
-
MockServer.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
ms = MockServer.new
|
30
|
+
ms.expects(:receive_data).at_least_once
|
31
|
+
s = ServerMock.new options[:host], options[:port], ms
|
32
|
+
Thread.new { subject.start }
|
33
|
+
sleep 0.2
|
34
34
|
end
|
35
35
|
|
36
36
|
it { should be_started }
|
@@ -89,8 +89,8 @@ module RubyAMI
|
|
89
89
|
end
|
90
90
|
|
91
91
|
describe 'when the events stream disconnects' do
|
92
|
-
it 'should
|
93
|
-
subject.expects(:
|
92
|
+
it 'should stop' do
|
93
|
+
subject.expects(:stop).once
|
94
94
|
subject.handle_event Stream::Disconnected.new
|
95
95
|
event_handler.should be_empty
|
96
96
|
end
|
@@ -117,8 +117,8 @@ module RubyAMI
|
|
117
117
|
action.should be_new
|
118
118
|
end
|
119
119
|
|
120
|
-
it 'should
|
121
|
-
subject.expects(:
|
120
|
+
it 'should stop' do
|
121
|
+
subject.expects(:stop).once
|
122
122
|
subject.handle_message Stream::Disconnected.new
|
123
123
|
end
|
124
124
|
end
|
@@ -340,27 +340,9 @@ module RubyAMI
|
|
340
340
|
end
|
341
341
|
|
342
342
|
it 'should close both streams' do
|
343
|
-
streams.each { |s| s.expects :
|
343
|
+
streams.each { |s| s.expects :terminate }
|
344
344
|
subject.stop
|
345
345
|
end
|
346
346
|
end
|
347
|
-
|
348
|
-
describe '#unbind' do
|
349
|
-
context 'if EM is running' do
|
350
|
-
it 'shuts down EM' do
|
351
|
-
EM.expects(:reactor_running?).returns true
|
352
|
-
EM.expects(:stop)
|
353
|
-
subject.unbind
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
context 'if EM is not running' do
|
358
|
-
it 'does nothing' do
|
359
|
-
EM.expects(:reactor_running?).returns false
|
360
|
-
EM.expects(:stop).never
|
361
|
-
subject.unbind
|
362
|
-
end
|
363
|
-
end
|
364
|
-
end
|
365
347
|
end
|
366
348
|
end
|
data/spec/ruby_ami/event_spec.rb
CHANGED
@@ -2,6 +2,72 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module RubyAMI
|
4
4
|
describe Event do
|
5
|
-
|
5
|
+
describe "equality" do
|
6
|
+
context "with the same name and the same headers" do
|
7
|
+
let :event1 do
|
8
|
+
Event.new('Hangup').tap do |e|
|
9
|
+
e['Channel'] = 'SIP/101-3f3f'
|
10
|
+
e['Uniqueid'] = '1094154427.10'
|
11
|
+
e['Cause'] = '0'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let :event2 do
|
16
|
+
Event.new('Hangup').tap do |e|
|
17
|
+
e['Channel'] = 'SIP/101-3f3f'
|
18
|
+
e['Uniqueid'] = '1094154427.10'
|
19
|
+
e['Cause'] = '0'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be equal" do
|
24
|
+
event1.should be == event2
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with a different name and the same headers" do
|
29
|
+
let :event1 do
|
30
|
+
Event.new('Hangup').tap do |e|
|
31
|
+
e['Channel'] = 'SIP/101-3f3f'
|
32
|
+
e['Uniqueid'] = '1094154427.10'
|
33
|
+
e['Cause'] = '0'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
let :event2 do
|
38
|
+
Event.new('Foo').tap do |e|
|
39
|
+
e['Channel'] = 'SIP/101-3f3f'
|
40
|
+
e['Uniqueid'] = '1094154427.10'
|
41
|
+
e['Cause'] = '0'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not be equal" do
|
46
|
+
event1.should_not be == event2
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with the same name and different headers" do
|
51
|
+
let :event1 do
|
52
|
+
Event.new('Hangup').tap do |e|
|
53
|
+
e['Channel'] = 'SIP/101-3f3f'
|
54
|
+
e['Uniqueid'] = '1094154427.10'
|
55
|
+
e['Cause'] = '0'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
let :event2 do
|
60
|
+
Event.new('Hangup').tap do |e|
|
61
|
+
e['Channel'] = 'SIP/101-3f3f'
|
62
|
+
e['Uniqueid'] = '1094154427.10'
|
63
|
+
e['Cause'] = '1'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not be equal" do
|
68
|
+
event1.should_not be == event2
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
6
72
|
end # Event
|
7
73
|
end # RubyAMI
|
@@ -2,6 +2,50 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module RubyAMI
|
4
4
|
describe Response do
|
5
|
-
|
5
|
+
describe "equality" do
|
6
|
+
context "with the same headers" do
|
7
|
+
let :event1 do
|
8
|
+
Response.new.tap do |e|
|
9
|
+
e['Channel'] = 'SIP/101-3f3f'
|
10
|
+
e['Uniqueid'] = '1094154427.10'
|
11
|
+
e['Cause'] = '0'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let :event2 do
|
16
|
+
Response.new.tap do |e|
|
17
|
+
e['Channel'] = 'SIP/101-3f3f'
|
18
|
+
e['Uniqueid'] = '1094154427.10'
|
19
|
+
e['Cause'] = '0'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be equal" do
|
24
|
+
event1.should be == event2
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with different headers" do
|
29
|
+
let :event1 do
|
30
|
+
Response.new.tap do |e|
|
31
|
+
e['Channel'] = 'SIP/101-3f3f'
|
32
|
+
e['Uniqueid'] = '1094154427.10'
|
33
|
+
e['Cause'] = '0'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
let :event2 do
|
38
|
+
Response.new.tap do |e|
|
39
|
+
e['Channel'] = 'SIP/101-3f3f'
|
40
|
+
e['Uniqueid'] = '1094154427.10'
|
41
|
+
e['Cause'] = '1'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not be equal" do
|
46
|
+
event1.should_not be == event2
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
6
50
|
end # Response
|
7
51
|
end # RubyAMI
|
@@ -2,21 +2,33 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module RubyAMI
|
4
4
|
describe Stream do
|
5
|
-
|
6
|
-
MockServer.any_instance.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
|
7
|
-
EventMachine::run {
|
8
|
-
EM.add_timer(0.5) { EM.stop if EM.reactor_running? }
|
5
|
+
let(:server_port) { 50000 - rand(1000) }
|
9
6
|
|
10
|
-
|
7
|
+
before do
|
8
|
+
def client.message_received(message)
|
9
|
+
@messages ||= Queue.new
|
10
|
+
@messages << message
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
def client.messages
|
14
|
+
@messages
|
15
|
+
end
|
16
|
+
end
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
let :client_messages do
|
19
|
+
messages = []
|
20
|
+
messages << client.messages.pop until client.messages.empty?
|
21
|
+
messages
|
22
|
+
end
|
17
23
|
|
18
|
-
|
19
|
-
|
24
|
+
def mocked_server(times = nil, fake_client = nil, &block)
|
25
|
+
mock_target = MockServer.new
|
26
|
+
mock_target.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
|
27
|
+
s = ServerMock.new '127.0.0.1', server_port, mock_target
|
28
|
+
@stream = Stream.new '127.0.0.1', server_port, lambda { |m| client.message_received m }
|
29
|
+
fake_client.call if fake_client.respond_to? :call
|
30
|
+
s.join
|
31
|
+
@stream.join
|
20
32
|
end
|
21
33
|
|
22
34
|
def expect_connected_event
|
@@ -29,22 +41,11 @@ module RubyAMI
|
|
29
41
|
|
30
42
|
before { @sequence = 1 }
|
31
43
|
|
32
|
-
it 'can be started' do
|
33
|
-
EM.expects(:connect).with do |*params|
|
34
|
-
params[0].should == 'example.com'
|
35
|
-
params[1].should == 1234
|
36
|
-
params[2].should == Stream
|
37
|
-
params[3].should be_a Proc
|
38
|
-
end
|
39
|
-
|
40
|
-
Stream.start 'example.com', 1234, lambda {}
|
41
|
-
end
|
42
|
-
|
43
44
|
describe "after connection" do
|
44
45
|
it "should be started" do
|
45
46
|
expect_connected_event
|
46
47
|
expect_disconnected_event
|
47
|
-
mocked_server(
|
48
|
+
mocked_server(0) do |val, server|
|
48
49
|
@stream.started?.should be_true
|
49
50
|
end
|
50
51
|
end
|
@@ -60,23 +61,6 @@ module RubyAMI
|
|
60
61
|
end
|
61
62
|
|
62
63
|
it 'sends events to the client when the stream is ready' do
|
63
|
-
client.expects(:message_received).times(3).with do |e|
|
64
|
-
case @sequence
|
65
|
-
when 1
|
66
|
-
e.should be_a Stream::Connected
|
67
|
-
when 2
|
68
|
-
EM.stop
|
69
|
-
e.should be_a Event
|
70
|
-
e.name.should == 'Hangup'
|
71
|
-
e['Channel'].should == 'SIP/101-3f3f'
|
72
|
-
e['Uniqueid'].should == '1094154427.10'
|
73
|
-
e['Cause'].should == '0'
|
74
|
-
when 3
|
75
|
-
e.should be_a Stream::Disconnected
|
76
|
-
end
|
77
|
-
@sequence += 1
|
78
|
-
end
|
79
|
-
|
80
64
|
mocked_server(1, lambda { @stream.send_data 'Foo' }) do |val, server|
|
81
65
|
server.send_data <<-EVENT
|
82
66
|
Event: Hangup
|
@@ -86,24 +70,19 @@ Cause: 0
|
|
86
70
|
|
87
71
|
EVENT
|
88
72
|
end
|
73
|
+
|
74
|
+
client_messages.should be == [
|
75
|
+
Stream::Connected.new,
|
76
|
+
Event.new('Hangup').tap do |e|
|
77
|
+
e['Channel'] = 'SIP/101-3f3f'
|
78
|
+
e['Uniqueid'] = '1094154427.10'
|
79
|
+
e['Cause'] = '0'
|
80
|
+
end,
|
81
|
+
Stream::Disconnected.new
|
82
|
+
]
|
89
83
|
end
|
90
84
|
|
91
85
|
it 'sends responses to the client when the stream is ready' do
|
92
|
-
client.expects(:message_received).times(3).with do |r|
|
93
|
-
case @sequence
|
94
|
-
when 1
|
95
|
-
r.should be_a Stream::Connected
|
96
|
-
when 2
|
97
|
-
EM.stop
|
98
|
-
r.should be_a Response
|
99
|
-
r['ActionID'].should == 'ee33eru2398fjj290'
|
100
|
-
r['Message'].should == 'Authentication accepted'
|
101
|
-
when 3
|
102
|
-
r.should be_a Stream::Disconnected
|
103
|
-
end
|
104
|
-
@sequence += 1
|
105
|
-
end
|
106
|
-
|
107
86
|
mocked_server(1, lambda { @stream.send_data 'Foo' }) do |val, server|
|
108
87
|
server.send_data <<-EVENT
|
109
88
|
Response: Success
|
@@ -112,6 +91,15 @@ Message: Authentication accepted
|
|
112
91
|
|
113
92
|
EVENT
|
114
93
|
end
|
94
|
+
|
95
|
+
client_messages.should be == [
|
96
|
+
Stream::Connected.new,
|
97
|
+
Response.new.tap do |r|
|
98
|
+
r['ActionID'] = 'ee33eru2398fjj290'
|
99
|
+
r['Message'] = 'Authentication accepted'
|
100
|
+
end,
|
101
|
+
Stream::Disconnected.new
|
102
|
+
]
|
115
103
|
end
|
116
104
|
|
117
105
|
it 'sends error to the client when the stream is ready and a bad command was send' do
|
@@ -120,7 +108,6 @@ Message: Authentication accepted
|
|
120
108
|
when 1
|
121
109
|
r.should be_a Stream::Connected
|
122
110
|
when 2
|
123
|
-
EM.stop
|
124
111
|
r.should be_a Error
|
125
112
|
r['ActionID'].should == 'ee33eru2398fjj290'
|
126
113
|
r['Message'].should == 'You stupid git'
|
@@ -144,10 +131,9 @@ Message: You stupid git
|
|
144
131
|
expect_connected_event
|
145
132
|
expect_disconnected_event
|
146
133
|
mocked_server(1, lambda { @stream.send_data 'Foo' }) do |val, server|
|
147
|
-
EM.stop
|
148
134
|
@stream.stopped?.should be false
|
149
135
|
end
|
150
|
-
@stream.
|
136
|
+
@stream.alive?.should be false
|
151
137
|
end
|
152
138
|
end
|
153
139
|
end
|
data/spec/support/mock_server.rb
CHANGED
@@ -1,13 +1,41 @@
|
|
1
1
|
MockServer = Class.new
|
2
2
|
|
3
|
-
|
3
|
+
class ServerMock
|
4
|
+
include Celluloid::IO
|
5
|
+
|
6
|
+
def initialize(host, port, mock_target = MockServer.new)
|
7
|
+
puts "*** Starting echo server on #{host}:#{port}"
|
8
|
+
@server = TCPServer.new host, port
|
9
|
+
@mock_target = mock_target
|
10
|
+
@clients = []
|
11
|
+
run!
|
12
|
+
end
|
13
|
+
|
14
|
+
def finalize
|
15
|
+
Logger.debug "ServerMock finalizing"
|
16
|
+
@server.close if @server
|
17
|
+
@clients.each(&:close)
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
after(0.5) { terminate }
|
22
|
+
loop { handle_connection! @server.accept }
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_connection(socket)
|
26
|
+
@clients << socket
|
27
|
+
_, port, host = socket.peeraddr
|
28
|
+
puts "*** Received connection from #{host}:#{port}"
|
29
|
+
loop { receive_data socket.readpartial(4096) }
|
30
|
+
end
|
31
|
+
|
4
32
|
def receive_data(data)
|
5
|
-
|
6
|
-
@
|
33
|
+
Logger.debug "ServerMock receiving data: #{data}"
|
34
|
+
@mock_target.receive_data data, self
|
7
35
|
end
|
8
36
|
|
9
37
|
def send_data(data)
|
10
|
-
|
38
|
+
@clients.each { |client| client.write data.gsub("\n", "\r\n") }
|
11
39
|
end
|
12
40
|
end
|
13
41
|
|
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: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,24 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: activesupport
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '3.0'
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '3.0'
|
30
14
|
- !ruby/object:Gem::Dependency
|
31
15
|
name: uuidtools
|
32
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,21 +28,21 @@ dependencies:
|
|
44
28
|
- !ruby/object:Gem::Version
|
45
29
|
version: '0'
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
31
|
+
name: celluloid-io
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
49
33
|
none: false
|
50
34
|
requirements:
|
51
|
-
- -
|
35
|
+
- - ~>
|
52
36
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
37
|
+
version: 0.11.0
|
54
38
|
type: :runtime
|
55
39
|
prerelease: false
|
56
40
|
version_requirements: !ruby/object:Gem::Requirement
|
57
41
|
none: false
|
58
42
|
requirements:
|
59
|
-
- -
|
43
|
+
- - ~>
|
60
44
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
45
|
+
version: 0.11.0
|
62
46
|
- !ruby/object:Gem::Dependency
|
63
47
|
name: future-resource
|
64
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -107,22 +91,6 @@ dependencies:
|
|
107
91
|
- - ~>
|
108
92
|
- !ruby/object:Gem::Version
|
109
93
|
version: '1.0'
|
110
|
-
- !ruby/object:Gem::Dependency
|
111
|
-
name: i18n
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
|
-
requirements:
|
115
|
-
- - ! '>='
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :runtime
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
|
-
requirements:
|
123
|
-
- - ! '>='
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '0'
|
126
94
|
- !ruby/object:Gem::Dependency
|
127
95
|
name: bundler
|
128
96
|
requirement: !ruby/object:Gem::Requirement
|
@@ -324,7 +292,6 @@ files:
|
|
324
292
|
- features/support/introspective_lexer.rb
|
325
293
|
- features/support/lexer_helper.rb
|
326
294
|
- lib/ruby_ami.rb
|
327
|
-
- lib/ruby_ami/Guardfile
|
328
295
|
- lib/ruby_ami/action.rb
|
329
296
|
- lib/ruby_ami/client.rb
|
330
297
|
- lib/ruby_ami/error.rb
|
@@ -359,7 +326,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
359
326
|
version: '0'
|
360
327
|
segments:
|
361
328
|
- 0
|
362
|
-
hash:
|
329
|
+
hash: 3703213424052847614
|
363
330
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
364
331
|
none: false
|
365
332
|
requirements:
|
@@ -368,10 +335,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
368
335
|
version: '0'
|
369
336
|
segments:
|
370
337
|
- 0
|
371
|
-
hash:
|
338
|
+
hash: 3703213424052847614
|
372
339
|
requirements: []
|
373
340
|
rubyforge_project: ruby_ami
|
374
|
-
rubygems_version: 1.8.
|
341
|
+
rubygems_version: 1.8.24
|
375
342
|
signing_key:
|
376
343
|
specification_version: 3
|
377
344
|
summary: Futzing with AMI so you don't have to
|