amf_socket 0.2.0 → 0.3.0
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/.rspec +1 -0
- data/Gemfile.lock +42 -1
- data/Guardfile +5 -0
- data/Rakefile +10 -5
- data/amf_socket.gemspec +7 -0
- data/lib/amf_socket/amf_rpc_connection.rb +61 -3
- data/lib/amf_socket/heartbeat.rb +51 -0
- data/lib/amf_socket/rpc_message.rb +7 -0
- data/lib/amf_socket/rpc_received_request.rb +2 -0
- data/lib/amf_socket/rpc_request.rb +38 -2
- data/lib/amf_socket/version.rb +1 -1
- data/lib/amf_socket.rb +32 -0
- data/spec/amf_socket/amf_connection_spec.rb +8 -0
- data/spec/amf_socket/amf_rpc_connection_spec.rb +196 -0
- data/spec/amf_socket/heartbeat_spec.rb +4 -0
- data/spec/amf_socket/rpc_message_spec.rb +29 -0
- data/spec/amf_socket/rpc_received_message_spec.rb +25 -0
- data/spec/amf_socket/rpc_received_request_spec.rb +35 -0
- data/spec/amf_socket/rpc_request_spec.rb +67 -0
- data/spec/amf_socket/rpc_response_spec.rb +20 -0
- data/spec/amf_socket/serializer_spec.rb +11 -0
- data/spec/amf_socket_spec.rb +7 -0
- data/spec/spec_helper.rb +30 -0
- metadata +126 -5
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
amf_socket (0.
|
4
|
+
amf_socket (0.3.0)
|
5
5
|
RocketAMF (>= 0.2.1)
|
6
6
|
eventmachine (>= 0.12.10)
|
7
7
|
|
@@ -9,10 +9,51 @@ GEM
|
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
11
|
RocketAMF (0.2.1)
|
12
|
+
columnize (0.3.6)
|
13
|
+
debugger (1.2.0)
|
14
|
+
columnize (>= 0.3.1)
|
15
|
+
debugger-linecache (~> 1.1.1)
|
16
|
+
debugger-ruby_core_source (~> 1.1.3)
|
17
|
+
debugger-linecache (1.1.2)
|
18
|
+
debugger-ruby_core_source (>= 1.1.1)
|
19
|
+
debugger-ruby_core_source (1.1.3)
|
20
|
+
diff-lcs (1.1.3)
|
12
21
|
eventmachine (0.12.10)
|
22
|
+
ffi (1.1.5)
|
23
|
+
growl (1.0.3)
|
24
|
+
guard (1.3.2)
|
25
|
+
listen (>= 0.4.2)
|
26
|
+
thor (>= 0.14.6)
|
27
|
+
guard-rspec (1.2.1)
|
28
|
+
guard (>= 1.1)
|
29
|
+
listen (0.4.7)
|
30
|
+
rb-fchange (~> 0.0.5)
|
31
|
+
rb-fsevent (~> 0.9.1)
|
32
|
+
rb-inotify (~> 0.8.8)
|
33
|
+
rake (0.9.2.2)
|
34
|
+
rb-fchange (0.0.5)
|
35
|
+
ffi
|
36
|
+
rb-fsevent (0.9.1)
|
37
|
+
rb-inotify (0.8.8)
|
38
|
+
ffi (>= 0.5.0)
|
39
|
+
rspec (2.11.0)
|
40
|
+
rspec-core (~> 2.11.0)
|
41
|
+
rspec-expectations (~> 2.11.0)
|
42
|
+
rspec-mocks (~> 2.11.0)
|
43
|
+
rspec-core (2.11.1)
|
44
|
+
rspec-expectations (2.11.2)
|
45
|
+
diff-lcs (~> 1.1.3)
|
46
|
+
rspec-mocks (2.11.2)
|
47
|
+
thor (0.16.0)
|
13
48
|
|
14
49
|
PLATFORMS
|
15
50
|
ruby
|
16
51
|
|
17
52
|
DEPENDENCIES
|
18
53
|
amf_socket!
|
54
|
+
debugger (= 1.2.0)
|
55
|
+
growl (= 1.0.3)
|
56
|
+
guard (= 1.3.2)
|
57
|
+
guard-rspec (= 1.2.1)
|
58
|
+
rake (= 0.9.2.2)
|
59
|
+
rspec (= 2.11.0)
|
data/Guardfile
ADDED
data/Rakefile
CHANGED
@@ -3,11 +3,6 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'bundler/gem_tasks'
|
5
5
|
|
6
|
-
begin
|
7
|
-
require 'debugger'
|
8
|
-
rescue Exception
|
9
|
-
end
|
10
|
-
|
11
6
|
begin
|
12
7
|
Bundler.setup(:default, :development)
|
13
8
|
rescue Bundler::BundlerError => e
|
@@ -16,6 +11,8 @@ rescue Bundler::BundlerError => e
|
|
16
11
|
exit e.status_code
|
17
12
|
end
|
18
13
|
|
14
|
+
require 'debugger'
|
15
|
+
|
19
16
|
task :environment do
|
20
17
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
21
18
|
require 'amf_socket'
|
@@ -30,6 +27,14 @@ task :console => :environment do
|
|
30
27
|
IRB.start
|
31
28
|
end
|
32
29
|
|
30
|
+
desc 'Run all specs'
|
31
|
+
task :spec do
|
32
|
+
puts 'Running rspec:'
|
33
|
+
system 'rspec spec'
|
34
|
+
end
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
33
38
|
desc 'Start a test server'
|
34
39
|
task :harness => :environment do
|
35
40
|
EM.run do
|
data/amf_socket.gemspec
CHANGED
@@ -17,4 +17,11 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_dependency('eventmachine', ['>= 0.12.10'])
|
19
19
|
gem.add_dependency('RocketAMF', ['>= 0.2.1'])
|
20
|
+
|
21
|
+
gem.add_development_dependency('rake', ['= 0.9.2.2'])
|
22
|
+
gem.add_development_dependency('rspec', ['= 2.11.0'])
|
23
|
+
gem.add_development_dependency('guard', ['= 1.3.2'])
|
24
|
+
gem.add_development_dependency('guard-rspec', ['= 1.2.1'])
|
25
|
+
gem.add_development_dependency('growl', ['= 1.0.3'])
|
26
|
+
gem.add_development_dependency('debugger', ['= 1.2.0'])
|
20
27
|
end
|
@@ -1,14 +1,20 @@
|
|
1
1
|
class AmfSocket::AmfRpcConnection < AmfSocket::AmfConnection
|
2
|
+
PING_INTERVAL = 5 # Seconds.
|
3
|
+
|
4
|
+
attr_reader :latency
|
5
|
+
|
2
6
|
def send_request(command, params = {}, &block)
|
3
7
|
request = AmfSocket::RpcRequest.new(command, params)
|
4
8
|
block.call(request)
|
5
9
|
@sent_requests[request.message_id] = request
|
6
10
|
send_object(request.to_hash)
|
11
|
+
request.send(:sent)
|
7
12
|
end
|
8
13
|
|
9
14
|
def send_message(command, params = {})
|
10
15
|
message = AmfSocket::RpcMessage.new(command, params)
|
11
16
|
send_object(message.to_hash)
|
17
|
+
message.send(:sent)
|
12
18
|
end
|
13
19
|
|
14
20
|
#
|
@@ -17,7 +23,11 @@ class AmfSocket::AmfRpcConnection < AmfSocket::AmfConnection
|
|
17
23
|
|
18
24
|
def post_init
|
19
25
|
super
|
26
|
+
|
20
27
|
@sent_requests = {}
|
28
|
+
@next_ping = Time.now.utc
|
29
|
+
|
30
|
+
AmfSocket.heartbeat.add(self)
|
21
31
|
end
|
22
32
|
|
23
33
|
def receive_object(object)
|
@@ -42,6 +52,8 @@ class AmfSocket::AmfRpcConnection < AmfSocket::AmfConnection
|
|
42
52
|
end
|
43
53
|
|
44
54
|
def unbind
|
55
|
+
AmfSocket.heartbeat.remove(self)
|
56
|
+
|
45
57
|
@sent_requests.each do |message_id, request|
|
46
58
|
if request.failed_callback.is_a?(Proc)
|
47
59
|
request.failed_callback.call('disconnected')
|
@@ -66,13 +78,59 @@ class AmfSocket::AmfRpcConnection < AmfSocket::AmfConnection
|
|
66
78
|
|
67
79
|
def receive_response(response_object)
|
68
80
|
raise AmfSocket::InvalidObject unless (message_id = response_object[:response][:messageId])
|
69
|
-
|
81
|
+
|
82
|
+
return unless (request = @sent_requests[message_id]) # Ignore timed out requests.
|
70
83
|
|
71
84
|
response = AmfSocket::RpcResponse.new(request, response_object)
|
72
85
|
@sent_requests.delete(message_id)
|
73
86
|
|
74
|
-
|
75
|
-
request.succeeded_callback.
|
87
|
+
AmfSocket.try do
|
88
|
+
if request.succeeded_callback.is_a?(Proc)
|
89
|
+
request.succeeded_callback.call(response)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def heartbeat
|
95
|
+
timeout_requests
|
96
|
+
ping
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Private Methods.
|
101
|
+
#
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def timeout_requests
|
106
|
+
@sent_requests.each do |message_id, request|
|
107
|
+
if request.timed_out?
|
108
|
+
AmfSocket.try do
|
109
|
+
if request.failed_callback.is_a?(Proc)
|
110
|
+
request.failed_callback.call('timed_out')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
@sent_requests.delete(message_id)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def ping
|
120
|
+
return if @next_ping > Time.now.utc
|
121
|
+
|
122
|
+
send_request('amf_socket_ping', :time => Time.now.utc, :latency => @latency.to_f) do |request|
|
123
|
+
@next_ping = Time.now.utc + PING_INTERVAL
|
124
|
+
|
125
|
+
request.timeout = 10
|
126
|
+
|
127
|
+
request.succeeded do |response|
|
128
|
+
@latency = Time.now.utc - request.sent_at
|
129
|
+
end
|
130
|
+
|
131
|
+
request.failed do |reason|
|
132
|
+
close_connection if reason == 'timed_out'
|
133
|
+
end
|
76
134
|
end
|
77
135
|
end
|
78
136
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class AmfSocket::Heartbeat
|
2
|
+
INTERVAL = 1 # Seconds.
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@objects = Set.new
|
6
|
+
start unless AmfSocket.test_mode?
|
7
|
+
end
|
8
|
+
|
9
|
+
def start
|
10
|
+
return false unless @timer.nil?
|
11
|
+
|
12
|
+
@timer = EM::PeriodicTimer.new(INTERVAL, method(:timer_handler))
|
13
|
+
|
14
|
+
return true
|
15
|
+
end
|
16
|
+
|
17
|
+
def stop
|
18
|
+
return false unless @timer
|
19
|
+
|
20
|
+
@timer.cancel
|
21
|
+
@timer = nil
|
22
|
+
|
23
|
+
return true
|
24
|
+
end
|
25
|
+
|
26
|
+
def add(object)
|
27
|
+
return false if @objects.include?(object)
|
28
|
+
|
29
|
+
@objects.add(object)
|
30
|
+
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
|
34
|
+
def remove(object)
|
35
|
+
return false unless @objects.include?(object)
|
36
|
+
|
37
|
+
@objects.delete(object)
|
38
|
+
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def timer_handler
|
45
|
+
@objects.each do |object|
|
46
|
+
AmfSocket.try do
|
47
|
+
object.send(:heartbeat) if object.respond_to?(:heartbeat, true)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -2,6 +2,7 @@ class AmfSocket::RpcMessage
|
|
2
2
|
attr_reader :message_id
|
3
3
|
attr_reader :command
|
4
4
|
attr_reader :params
|
5
|
+
attr_reader :sent_at
|
5
6
|
|
6
7
|
def initialize(command, params = {})
|
7
8
|
raise AmfSocket::InvalidArg.new('Command must be a String.') unless command.is_a?(String)
|
@@ -23,4 +24,10 @@ class AmfSocket::RpcMessage
|
|
23
24
|
|
24
25
|
return object
|
25
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def sent
|
31
|
+
@sent_at = Time.now.utc
|
32
|
+
end
|
26
33
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
class AmfSocket::RpcRequest
|
2
|
-
attr_reader :state # Valid states: :initialized, :sent, :responded.
|
2
|
+
attr_reader :state # Valid states: :initialized, :sent, :responded, :failed.
|
3
3
|
attr_reader :message_id
|
4
4
|
attr_reader :command
|
5
5
|
attr_reader :params
|
6
|
+
attr_reader :sent_at
|
7
|
+
attr_reader :timeout_at
|
6
8
|
|
7
9
|
attr_accessor :succeeded_callback
|
8
10
|
attr_accessor :failed_callback
|
9
|
-
|
11
|
+
|
12
|
+
TIMEOUT = 30 # Seconds.
|
10
13
|
|
11
14
|
def initialize(command, params = {})
|
12
15
|
raise AmfSocket::InvalidArg.new('Command must be a String.') unless command.is_a?(String)
|
@@ -16,13 +19,18 @@ class AmfSocket::RpcRequest
|
|
16
19
|
@params = params
|
17
20
|
@state = :initialized
|
18
21
|
@message_id = SecureRandom.hex
|
22
|
+
@timeout = TIMEOUT
|
19
23
|
end
|
20
24
|
|
21
25
|
def succeeded(&block)
|
26
|
+
require_state(:initialized)
|
27
|
+
|
22
28
|
@succeeded_callback = block
|
23
29
|
end
|
24
30
|
|
25
31
|
def failed(&block)
|
32
|
+
require_state(:initialized)
|
33
|
+
|
26
34
|
@failed_callback = block
|
27
35
|
end
|
28
36
|
|
@@ -37,4 +45,32 @@ class AmfSocket::RpcRequest
|
|
37
45
|
|
38
46
|
return object
|
39
47
|
end
|
48
|
+
|
49
|
+
def timeout=(seconds)
|
50
|
+
require_state(:initialized)
|
51
|
+
|
52
|
+
@timeout = seconds
|
53
|
+
end
|
54
|
+
|
55
|
+
def timeout
|
56
|
+
return @timeout
|
57
|
+
end
|
58
|
+
|
59
|
+
def timed_out?
|
60
|
+
return Time.now.utc >= @timeout_at
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def sent
|
66
|
+
require_state(:initialized)
|
67
|
+
|
68
|
+
@state = :sent
|
69
|
+
@sent_at = Time.now.utc
|
70
|
+
@timeout_at = @sent_at + timeout
|
71
|
+
end
|
72
|
+
|
73
|
+
def require_state(s)
|
74
|
+
raise 'Invalid state' unless @state == s
|
75
|
+
end
|
40
76
|
end
|
data/lib/amf_socket/version.rb
CHANGED
data/lib/amf_socket.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
require 'rocketamf'
|
3
3
|
require 'securerandom'
|
4
|
+
require 'thread'
|
4
5
|
|
5
6
|
module AmfSocket; end
|
6
7
|
|
@@ -14,3 +15,34 @@ require 'amf_socket/rpc_received_request'
|
|
14
15
|
require 'amf_socket/rpc_received_message'
|
15
16
|
require 'amf_socket/serializer'
|
16
17
|
require 'amf_socket/exceptions'
|
18
|
+
require 'amf_socket/heartbeat'
|
19
|
+
|
20
|
+
module AmfSocket
|
21
|
+
def self.heartbeat
|
22
|
+
@heartbeat ||= AmfSocket::Heartbeat.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.exception_handler=(handler)
|
26
|
+
@exception_handler = handler
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.exception_handler
|
30
|
+
return @exception_handler
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.try(&block)
|
34
|
+
begin
|
35
|
+
block.call
|
36
|
+
rescue Exception => e
|
37
|
+
@exception_handler.call(e) if @exception_handler
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.enable_test_mode
|
42
|
+
@test_mode = true
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.test_mode?
|
46
|
+
return !!@test_mode
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class AmfRpcConnTestable < AmfSocket::AmfRpcConnection
|
4
|
+
attr_accessor :sent_requests
|
5
|
+
attr_accessor :sent_objects
|
6
|
+
attr_accessor :received_requests
|
7
|
+
attr_accessor :received_messages
|
8
|
+
|
9
|
+
def self.new
|
10
|
+
allocate.instance_eval do
|
11
|
+
initialize
|
12
|
+
post_init
|
13
|
+
self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@sent_objects = []
|
19
|
+
@received_requests = []
|
20
|
+
@received_messages = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def send_object(object)
|
24
|
+
@sent_objects << object
|
25
|
+
end
|
26
|
+
|
27
|
+
def receive_request(request)
|
28
|
+
@received_requests << request
|
29
|
+
end
|
30
|
+
|
31
|
+
def receive_message(message)
|
32
|
+
@received_messages << message
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe AmfSocket::AmfRpcConnection do
|
37
|
+
context 'when sending requests' do
|
38
|
+
before(:each) do
|
39
|
+
@conn = AmfRpcConnTestable.new
|
40
|
+
@command = 'hello'
|
41
|
+
@params = { :foo => 'bar' }
|
42
|
+
@request = AmfSocket::RpcRequest.new(@command, @params)
|
43
|
+
@flag = false
|
44
|
+
@block = proc do |request|
|
45
|
+
@flag = true
|
46
|
+
@block_arg = request
|
47
|
+
end
|
48
|
+
|
49
|
+
AmfSocket::RpcRequest.should_receive(:new).with(@command, @params).and_return(@request)
|
50
|
+
|
51
|
+
@conn.send_request(@command, @params) { |request| @block.call(request) }
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should send the request as a simple hash object' do
|
55
|
+
@conn.sent_objects.first.should == @request.to_hash
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should execute the block and pass it a request object' do
|
59
|
+
@flag.should == true
|
60
|
+
@block_arg.class.should == AmfSocket::RpcRequest
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should register the request in order to handle the response' do
|
64
|
+
@conn.sent_requests.first[0].should == @request.message_id
|
65
|
+
@conn.sent_requests.first[1].should == @request
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when sending messages' do
|
70
|
+
before(:each) do
|
71
|
+
@conn = AmfRpcConnTestable.new
|
72
|
+
@command = 'hello'
|
73
|
+
@params = { :foo => 'bar' }
|
74
|
+
@message = AmfSocket::RpcMessage.new(@command, @params)
|
75
|
+
|
76
|
+
AmfSocket::RpcMessage.should_receive(:new).with(@command, @params).and_return(@message)
|
77
|
+
|
78
|
+
@conn.send_message(@command, @params)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should send the message as a simple hash object' do
|
82
|
+
@conn.sent_objects.first.should == @message.to_hash
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when receiving objects' do
|
87
|
+
before(:each) do
|
88
|
+
@conn = AmfRpcConnTestable.new
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should handle received requests' do
|
92
|
+
object = {
|
93
|
+
:type => 'rpcRequest',
|
94
|
+
:request => {
|
95
|
+
:messageId => '123',
|
96
|
+
:command => 'hello',
|
97
|
+
:params => {
|
98
|
+
:foo => 'bar'
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
@conn.receive_object(object)
|
104
|
+
|
105
|
+
@conn.received_requests.length.should == 1
|
106
|
+
|
107
|
+
request = @conn.received_requests.first
|
108
|
+
|
109
|
+
request.class.should == AmfSocket::RpcReceivedRequest
|
110
|
+
request.message_id.should == '123'
|
111
|
+
request.command.should == 'hello'
|
112
|
+
request.params.should == { :foo => 'bar' }
|
113
|
+
request.connection.should == @conn
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should handle recevied messages' do
|
117
|
+
object = {
|
118
|
+
:type => 'rpcMessage',
|
119
|
+
:message => {
|
120
|
+
:messageId => '123',
|
121
|
+
:command => 'hello',
|
122
|
+
:params => {
|
123
|
+
:foo => 'bar'
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
@conn.receive_object(object)
|
129
|
+
|
130
|
+
@conn.received_messages.length.should == 1
|
131
|
+
|
132
|
+
message = @conn.received_messages.first
|
133
|
+
|
134
|
+
message.class.should == AmfSocket::RpcReceivedMessage
|
135
|
+
message.message_id.should == '123'
|
136
|
+
message.command.should == 'hello'
|
137
|
+
message.params.should == { :foo => 'bar' }
|
138
|
+
message.connection.should == @conn
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should handle responses for sent requests' do
|
142
|
+
flag = false
|
143
|
+
req = nil
|
144
|
+
res = nil
|
145
|
+
|
146
|
+
@conn.send_request('hello', :foo => 'bar') do |request|
|
147
|
+
req = request
|
148
|
+
|
149
|
+
request.succeeded do |response|
|
150
|
+
flag = true
|
151
|
+
res = response
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
object = {
|
156
|
+
:type => 'rpcResponse',
|
157
|
+
:response => {
|
158
|
+
:messageId => req.message_id,
|
159
|
+
:result => 'happy ending'
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
@conn.receive_object(object)
|
164
|
+
|
165
|
+
flag.should == true
|
166
|
+
res.result.should == 'happy ending'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'when a socket gets disconnected' do
|
171
|
+
before(:each) do
|
172
|
+
@conn = AmfRpcConnTestable.new
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should trigger failure on app pending requests' do
|
176
|
+
flag = false
|
177
|
+
req = nil
|
178
|
+
reas = nil
|
179
|
+
|
180
|
+
@conn.send_request('hello', :foo => 'bar') do |request|
|
181
|
+
req = request
|
182
|
+
|
183
|
+
request.failed do |reason|
|
184
|
+
flag = true
|
185
|
+
reas = reason
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
@conn.unbind
|
190
|
+
|
191
|
+
flag.should == true
|
192
|
+
reas.should == 'disconnected'
|
193
|
+
@conn.sent_requests.length.should == 0
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AmfSocket::RpcMessage do
|
4
|
+
it 'should construct properly' do
|
5
|
+
SecureRandom.should_receive(:hex).and_return('random id')
|
6
|
+
|
7
|
+
message = AmfSocket::RpcMessage.new('hello', :foo => 'bar')
|
8
|
+
|
9
|
+
message.message_id.should == 'random id'
|
10
|
+
message.command.should == 'hello'
|
11
|
+
message.params.should == { :foo => 'bar' }
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should convert to a hash' do
|
15
|
+
message = AmfSocket::RpcMessage.new('hello', :foo => 'bar')
|
16
|
+
|
17
|
+
expected = {
|
18
|
+
:type => 'rpcMessage',
|
19
|
+
:message => {
|
20
|
+
:messageId => message.message_id,
|
21
|
+
:command => 'hello',
|
22
|
+
:params => { :foo => 'bar'
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
message.to_hash.should == expected
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AmfSocket::RpcReceivedMessage do
|
4
|
+
it 'should construct properly' do
|
5
|
+
object = {
|
6
|
+
:type => 'rpcMessage',
|
7
|
+
:message => {
|
8
|
+
:messageId => 'random id',
|
9
|
+
:command => 'hello',
|
10
|
+
:params => {
|
11
|
+
:foo => 'bar'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
conn = stub
|
17
|
+
|
18
|
+
message = AmfSocket::RpcReceivedMessage.new(object, conn)
|
19
|
+
|
20
|
+
message.connection.should == conn
|
21
|
+
message.message_id.should == 'random id'
|
22
|
+
message.command.should == 'hello'
|
23
|
+
message.params.should == { :foo => 'bar' }
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AmfSocket::RpcReceivedRequest do
|
4
|
+
before(:each) do
|
5
|
+
@object = {
|
6
|
+
:type => 'rpcRequest',
|
7
|
+
:request => {
|
8
|
+
:messageId => 'random id',
|
9
|
+
:command => 'hello',
|
10
|
+
:params => {
|
11
|
+
:foo => 'bar'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
@conn = stub
|
17
|
+
|
18
|
+
@request = AmfSocket::RpcReceivedRequest.new(@object, @conn)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should construct properly' do
|
22
|
+
@request.state.should == :initialized
|
23
|
+
@request.connection.should == @conn
|
24
|
+
@request.message_id.should == 'random id'
|
25
|
+
@request.command.should == 'hello'
|
26
|
+
@request.params.should == { :foo => 'bar' }
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should reply properly' do
|
30
|
+
@conn.should_receive(:send_object).exactly(:once)
|
31
|
+
@request.reply('foo bar').should == true
|
32
|
+
@request.state.should == :replied
|
33
|
+
@request.reply('foo bar again').should == false
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AmfSocket::RpcRequest do
|
4
|
+
it 'should construct properly' do
|
5
|
+
SecureRandom.should_receive(:hex).and_return('random id')
|
6
|
+
|
7
|
+
request = AmfSocket::RpcRequest.new('hello', :foo => 'bar')
|
8
|
+
|
9
|
+
request.message_id.should == 'random id'
|
10
|
+
request.command.should == 'hello'
|
11
|
+
request.params.should == { :foo => 'bar' }
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should convert to a hash' do
|
15
|
+
request = AmfSocket::RpcRequest.new('hello', :foo => 'bar')
|
16
|
+
|
17
|
+
expected = {
|
18
|
+
:type=> 'rpcRequest',
|
19
|
+
:request => {
|
20
|
+
:messageId => request.message_id,
|
21
|
+
:command => 'hello',
|
22
|
+
:params=> { :foo => 'bar'
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
request.to_hash.should == expected
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should store the succeeded callback' do
|
31
|
+
request = AmfSocket::RpcRequest.new('hello', :foo => 'bar')
|
32
|
+
|
33
|
+
flag = false
|
34
|
+
|
35
|
+
request.succeeded { flag = true }
|
36
|
+
request.succeeded_callback.call
|
37
|
+
|
38
|
+
flag.should == true
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should store the failed callback' do
|
42
|
+
request = AmfSocket::RpcRequest.new('hello', :foo => 'bar')
|
43
|
+
|
44
|
+
flag = false
|
45
|
+
|
46
|
+
request.failed { flag = true }
|
47
|
+
request.failed_callback.call
|
48
|
+
|
49
|
+
flag.should == true
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should convert to a hash' do
|
53
|
+
message = AmfSocket::RpcRequest.new('hello', :foo => 'bar')
|
54
|
+
|
55
|
+
expected = {
|
56
|
+
:type => 'rpcRequest',
|
57
|
+
:request => {
|
58
|
+
:messageId => message.message_id,
|
59
|
+
:command => 'hello',
|
60
|
+
:params => { :foo => 'bar'
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
message.to_hash.should == expected
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AmfSocket::RpcResponse do
|
4
|
+
it 'should construct properly' do
|
5
|
+
request = stub
|
6
|
+
|
7
|
+
response_object = {
|
8
|
+
:type => 'rpcResponse',
|
9
|
+
:response => {
|
10
|
+
:messageId => 'random id',
|
11
|
+
:result => 'foobar'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
response = AmfSocket::RpcResponse.new(request, response_object)
|
16
|
+
|
17
|
+
response.request.should == request
|
18
|
+
response.result.should == 'foobar'
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AmfSocket::Serializer do
|
4
|
+
it 'should dump an object to AMF format' do
|
5
|
+
AmfSocket::Serializer.dump({ :foo => 'bar' }).should == "\n\v\x01\afoo\x06\abar\x01"
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should load an object from AMF format' do
|
9
|
+
AmfSocket::Serializer.load("\n\v\x01\afoo\x06\abar\x01").should == { :foo => 'bar' }
|
10
|
+
end
|
11
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
require 'debugger'
|
7
|
+
|
8
|
+
begin
|
9
|
+
Bundler.setup(:default, :development)
|
10
|
+
rescue Bundler::BundlerError => e
|
11
|
+
$stderr.puts(e.message)
|
12
|
+
$stderr.puts("Run `bundle install` to install missing gems")
|
13
|
+
exit e.status_code
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'benchmark'
|
17
|
+
require 'amf_socket'
|
18
|
+
|
19
|
+
AmfSocket.enable_test_mode
|
20
|
+
|
21
|
+
AmfSocket.exception_handler do |ue|
|
22
|
+
puts "UNHANDLED EXCEPTION #{ue.class} (#{ue.message.chomp})\n#{ue.backtrace.join("\n")}\n--"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Requires supporting files with custom matchers and macros, etc,
|
26
|
+
# in ./support/ and its subdirectories.
|
27
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
28
|
+
|
29
|
+
RSpec.configure do |config|
|
30
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amf_socket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -43,6 +43,102 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 0.2.1
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - '='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.2.2
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.9.2.2
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - '='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.11.0
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.11.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: guard
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - '='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.3.2
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - '='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.3.2
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: guard-rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - '='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.2.1
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - '='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.2.1
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: growl
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.0.3
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - '='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 1.0.3
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: debugger
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - '='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 1.2.0
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - '='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 1.2.0
|
46
142
|
description: Ruby implementation of AMF Socket (https://github.com/chadrem/amf_socket)
|
47
143
|
email:
|
48
144
|
- chad@remesch.com
|
@@ -51,8 +147,10 @@ extensions: []
|
|
51
147
|
extra_rdoc_files: []
|
52
148
|
files:
|
53
149
|
- .gitignore
|
150
|
+
- .rspec
|
54
151
|
- Gemfile
|
55
152
|
- Gemfile.lock
|
153
|
+
- Guardfile
|
56
154
|
- LICENSE.txt
|
57
155
|
- README.md
|
58
156
|
- Rakefile
|
@@ -61,6 +159,7 @@ files:
|
|
61
159
|
- lib/amf_socket/amf_connection.rb
|
62
160
|
- lib/amf_socket/amf_rpc_connection.rb
|
63
161
|
- lib/amf_socket/exceptions.rb
|
162
|
+
- lib/amf_socket/heartbeat.rb
|
64
163
|
- lib/amf_socket/rpc_message.rb
|
65
164
|
- lib/amf_socket/rpc_received_message.rb
|
66
165
|
- lib/amf_socket/rpc_received_request.rb
|
@@ -68,6 +167,17 @@ files:
|
|
68
167
|
- lib/amf_socket/rpc_response.rb
|
69
168
|
- lib/amf_socket/serializer.rb
|
70
169
|
- lib/amf_socket/version.rb
|
170
|
+
- spec/amf_socket/amf_connection_spec.rb
|
171
|
+
- spec/amf_socket/amf_rpc_connection_spec.rb
|
172
|
+
- spec/amf_socket/heartbeat_spec.rb
|
173
|
+
- spec/amf_socket/rpc_message_spec.rb
|
174
|
+
- spec/amf_socket/rpc_received_message_spec.rb
|
175
|
+
- spec/amf_socket/rpc_received_request_spec.rb
|
176
|
+
- spec/amf_socket/rpc_request_spec.rb
|
177
|
+
- spec/amf_socket/rpc_response_spec.rb
|
178
|
+
- spec/amf_socket/serializer_spec.rb
|
179
|
+
- spec/amf_socket_spec.rb
|
180
|
+
- spec/spec_helper.rb
|
71
181
|
homepage: https://github.com/chadrem/observation
|
72
182
|
licenses: []
|
73
183
|
post_install_message:
|
@@ -82,7 +192,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
192
|
version: '0'
|
83
193
|
segments:
|
84
194
|
- 0
|
85
|
-
hash: -
|
195
|
+
hash: -2517453312073385127
|
86
196
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
197
|
none: false
|
88
198
|
requirements:
|
@@ -91,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
201
|
version: '0'
|
92
202
|
segments:
|
93
203
|
- 0
|
94
|
-
hash: -
|
204
|
+
hash: -2517453312073385127
|
95
205
|
requirements: []
|
96
206
|
rubyforge_project:
|
97
207
|
rubygems_version: 1.8.24
|
@@ -99,4 +209,15 @@ signing_key:
|
|
99
209
|
specification_version: 3
|
100
210
|
summary: AMF Socket is a bi-directional RPC system for Adobe Flash (Actionscript)
|
101
211
|
programs.
|
102
|
-
test_files:
|
212
|
+
test_files:
|
213
|
+
- spec/amf_socket/amf_connection_spec.rb
|
214
|
+
- spec/amf_socket/amf_rpc_connection_spec.rb
|
215
|
+
- spec/amf_socket/heartbeat_spec.rb
|
216
|
+
- spec/amf_socket/rpc_message_spec.rb
|
217
|
+
- spec/amf_socket/rpc_received_message_spec.rb
|
218
|
+
- spec/amf_socket/rpc_received_request_spec.rb
|
219
|
+
- spec/amf_socket/rpc_request_spec.rb
|
220
|
+
- spec/amf_socket/rpc_response_spec.rb
|
221
|
+
- spec/amf_socket/serializer_spec.rb
|
222
|
+
- spec/amf_socket_spec.rb
|
223
|
+
- spec/spec_helper.rb
|