ruby_ami 1.0.1 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|