ione-rpc 1.0.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +5 -0
- data/README.md +267 -0
- data/lib/ione/rpc/client.rb +302 -0
- data/lib/ione/rpc/client_peer.rb +78 -0
- data/lib/ione/rpc/codec.rb +153 -0
- data/lib/ione/rpc/peer.rb +53 -0
- data/lib/ione/rpc/server.rb +101 -0
- data/lib/ione/rpc/version.rb +7 -0
- data/lib/ione/rpc.rb +15 -0
- data/spec/ione/rpc/client_peer_spec.rb +109 -0
- data/spec/ione/rpc/client_spec.rb +614 -0
- data/spec/ione/rpc/codec_spec.rb +153 -0
- data/spec/ione/rpc/peer_common.rb +137 -0
- data/spec/ione/rpc/server_spec.rb +214 -0
- data/spec/spec_helper.rb +23 -0
- metadata +80 -0
@@ -0,0 +1,153 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
module Ione
|
7
|
+
module Rpc
|
8
|
+
describe Codec do
|
9
|
+
let :codec do
|
10
|
+
CodecSpec::JsonCodec.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#encode' do
|
14
|
+
let :object do
|
15
|
+
{'foo' => 'bar', 'baz' => 42}
|
16
|
+
end
|
17
|
+
|
18
|
+
let :encoded_message do
|
19
|
+
codec.encode(object, 42)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'encodes the version in the first byte' do
|
23
|
+
encoded_message[0, 1].unpack('c').should == [1]
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'encodes the channel in the second byte' do
|
27
|
+
encoded_message[1, 1].unpack('c').should == [42]
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'encodes the length of the frame in the following four bytes' do
|
31
|
+
encoded_message[2, 4].unpack('N').should == [22]
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'encodes the object as JSON' do
|
35
|
+
encoded_message[6..-1].should == '{"foo":"bar","baz":42}'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#decode' do
|
40
|
+
let :object do
|
41
|
+
{'foo' => 'bar', 'baz' => 42}
|
42
|
+
end
|
43
|
+
|
44
|
+
let :encoded_message do
|
45
|
+
%(\x01\x2a\x00\x00\x00\x16{"foo":"bar","baz":42})
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns a partial message when there are less than five bytes' do
|
49
|
+
_, _, complete = codec.decode(Ione::ByteBuffer.new(encoded_message[0, 4]), nil)
|
50
|
+
complete.should be_false
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns a partial message when the combined size of a previous partial message an new data is still less than the full frame size' do
|
54
|
+
buffer = Ione::ByteBuffer.new
|
55
|
+
buffer << encoded_message[0, 10]
|
56
|
+
message, _, _ = codec.decode(buffer, nil)
|
57
|
+
buffer << encoded_message[10, 4]
|
58
|
+
_, _, complete = codec.decode(buffer, message)
|
59
|
+
complete.should be_false
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns a message and channel when it gets a full frame in one chunk' do
|
63
|
+
message, channel, complete = codec.decode(Ione::ByteBuffer.new(encoded_message), nil)
|
64
|
+
complete.should be_true
|
65
|
+
message.should == object
|
66
|
+
channel.should == 42
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'returns a message and channel when it gets a full frame in chunks' do
|
70
|
+
buffer = Ione::ByteBuffer.new
|
71
|
+
buffer << encoded_message[0, 4]
|
72
|
+
message, _, _ = codec.decode(buffer, nil)
|
73
|
+
buffer << encoded_message[4, 10]
|
74
|
+
message, _, _ = codec.decode(buffer, message)
|
75
|
+
buffer << encoded_message[14..-1]
|
76
|
+
message, channel, _ = codec.decode(buffer, message)
|
77
|
+
message.should == object
|
78
|
+
channel.should == 42
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'returns a message when it gets more bytes than needed' do
|
82
|
+
buffer = Ione::ByteBuffer.new
|
83
|
+
buffer << encoded_message[0, 10]
|
84
|
+
message, _ = codec.decode(buffer, message)
|
85
|
+
buffer << encoded_message[10..-1]
|
86
|
+
buffer << 'fooooo'
|
87
|
+
message, channel = codec.decode(buffer, message)
|
88
|
+
message.should == object
|
89
|
+
channel.should == 42
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when decoding and encoding' do
|
94
|
+
let :message do
|
95
|
+
{'foo' => 'bar', 'baz' => 42}
|
96
|
+
end
|
97
|
+
|
98
|
+
let :channel do
|
99
|
+
42
|
100
|
+
end
|
101
|
+
|
102
|
+
let :frame do
|
103
|
+
%(\x01\x2a\x00\x00\x00\x16{"foo":"bar","baz":42})
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'decoding a encoded frame returns the original message' do
|
107
|
+
frm = codec.encode(message, channel)
|
108
|
+
msg, ch, _ = codec.decode(Ione::ByteBuffer.new(frm), nil)
|
109
|
+
msg.should == message
|
110
|
+
ch.should == channel
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'encoding a message gives the original frame' do
|
114
|
+
msg, ch, _ = codec.decode(Ione::ByteBuffer.new(frame), nil)
|
115
|
+
frm = codec.encode(msg, ch)
|
116
|
+
frm.should == frame
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe StandardCodec do
|
122
|
+
let :codec do
|
123
|
+
described_class.new(JSON)
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#encode' do
|
127
|
+
it 'calls #dump on the delegate' do
|
128
|
+
codec.encode({'foo' => 'bar'}, 0)[6..-1].should == '{"foo":"bar"}'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#decode' do
|
133
|
+
it 'calls #load on the delegate' do
|
134
|
+
buffer = Ione::ByteBuffer.new(%(\x01\x00\x00\x00\x00\x0d{"foo":"bar"}))
|
135
|
+
message, _, _ = codec.decode(buffer, nil)
|
136
|
+
message.should eql('foo' => 'bar')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
module CodecSpec
|
144
|
+
class JsonCodec < Ione::Rpc::Codec
|
145
|
+
def encode_message(message)
|
146
|
+
JSON.dump(message)
|
147
|
+
end
|
148
|
+
|
149
|
+
def decode_message(str)
|
150
|
+
JSON.load(str)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
shared_examples 'peers' do
|
7
|
+
context 'when setting up' do
|
8
|
+
it 'registers itself to receive notifications when there is new data' do
|
9
|
+
connection.data_listener.should_not be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'registers itself to receive notifications when the connection closes' do
|
13
|
+
connection.closed_listener.should_not be_nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when receiving data' do
|
18
|
+
let :empty_frame do
|
19
|
+
double(:empty_frame, :partial? => true)
|
20
|
+
end
|
21
|
+
|
22
|
+
let :partial_frame do
|
23
|
+
double(:partial_frame, :partial? => true)
|
24
|
+
end
|
25
|
+
|
26
|
+
let :complete_frame do
|
27
|
+
double(:complete_frame, :partial? => false)
|
28
|
+
end
|
29
|
+
|
30
|
+
before do
|
31
|
+
channel = 9
|
32
|
+
codec.stub(:decode) do |buffer, previous_frame|
|
33
|
+
if buffer.empty?
|
34
|
+
[empty_frame, channel, false]
|
35
|
+
elsif buffer.index('FAKEPARTIALFRAME') == 0
|
36
|
+
buffer.read(16)
|
37
|
+
[partial_frame, channel, false]
|
38
|
+
elsif buffer.index('FAKEENDOFFRAME') == 0 && previous_frame == partial_frame
|
39
|
+
buffer.read(14)
|
40
|
+
[complete_frame, channel, true]
|
41
|
+
elsif buffer.index('FOO') == 0 || buffer.index('BAR') == 0 || buffer.index('BAZ') == 0
|
42
|
+
buffer.read(3)
|
43
|
+
[complete_frame, channel, true]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'does nothing when it\'s a partial frame' do
|
49
|
+
connection.data_listener.call('FAKEPARTIALFRAME')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'stiches together frames from fragments' do
|
53
|
+
connection.data_listener.call('FAKEPARTIALFRAME')
|
54
|
+
connection.data_listener.call('FAKEENDOFFRAME')
|
55
|
+
connection.written_bytes.should_not be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'delivers the decoded frames to #handle_message' do
|
59
|
+
connection.data_listener.call('FAKEPARTIALFRAME')
|
60
|
+
connection.data_listener.call('FAKEENDOFFRAME')
|
61
|
+
peer.messages.should == [[complete_frame, 9]]
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'delivers multiple frames to #handle_message' do
|
65
|
+
connection.data_listener.call('FOOBARBAZ')
|
66
|
+
peer.messages.should have(3).items
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when sending data' do
|
71
|
+
before do
|
72
|
+
codec.stub(:encode) do |message, channel|
|
73
|
+
"#{message}@#{channel}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'writes the encoded frame to the connection' do
|
78
|
+
peer.send_message('FUZZBAZZ')
|
79
|
+
codec.should have_received(:encode).with('FUZZBAZZ', 0)
|
80
|
+
connection.written_bytes.should == 'FUZZBAZZ@0'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when the connection closes' do
|
85
|
+
it 'calls the closed listeners' do
|
86
|
+
called1 = false
|
87
|
+
called2 = false
|
88
|
+
peer.on_closed { called1 = true }
|
89
|
+
peer.on_closed { called2 = true }
|
90
|
+
connection.closed_listener.call
|
91
|
+
called1.should be_true
|
92
|
+
called2.should be_true
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'calls the closed listener with the close cause' do
|
96
|
+
cause = nil
|
97
|
+
peer.on_closed { |e| cause = e }
|
98
|
+
connection.closed_listener.call(StandardError.new('foo'))
|
99
|
+
cause.should == StandardError.new('foo')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'when closed' do
|
104
|
+
before do
|
105
|
+
connection.stub(:close)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'closes the connection' do
|
109
|
+
peer.close
|
110
|
+
connection.should have_received(:close)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
module RpcSpec
|
116
|
+
class FakeConnection
|
117
|
+
attr_reader :written_bytes, :data_listener, :closed_listener, :host, :port
|
118
|
+
|
119
|
+
def initialize
|
120
|
+
@host = 'example.com'
|
121
|
+
@port = 9999
|
122
|
+
@written_bytes = ''
|
123
|
+
end
|
124
|
+
|
125
|
+
def write(bytes)
|
126
|
+
@written_bytes << bytes
|
127
|
+
end
|
128
|
+
|
129
|
+
def on_data(&listener)
|
130
|
+
@data_listener = listener
|
131
|
+
end
|
132
|
+
|
133
|
+
def on_closed(&listener)
|
134
|
+
@closed_listener = listener
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
module Ione
|
7
|
+
module Rpc
|
8
|
+
describe Server do
|
9
|
+
let :server do
|
10
|
+
ServerSpec::TestServer.new(4321, codec, io_reactor: io_reactor, logger: logger)
|
11
|
+
end
|
12
|
+
|
13
|
+
let :codec do
|
14
|
+
double(:codec)
|
15
|
+
end
|
16
|
+
|
17
|
+
let :logger do
|
18
|
+
double(:logger)
|
19
|
+
end
|
20
|
+
|
21
|
+
let :acceptor do
|
22
|
+
double(:acceptor)
|
23
|
+
end
|
24
|
+
|
25
|
+
let :io_reactor do
|
26
|
+
double(:io_reactor)
|
27
|
+
end
|
28
|
+
|
29
|
+
before do
|
30
|
+
io_reactor.stub(:start).and_return(Ione::Future.resolved(io_reactor))
|
31
|
+
io_reactor.stub(:stop).and_return(Ione::Future.resolved(io_reactor))
|
32
|
+
io_reactor.stub(:bind) do |*args, &callback|
|
33
|
+
callback.call(acceptor)
|
34
|
+
Ione::Future.resolved
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
before do
|
39
|
+
acceptor.stub(:on_accept)
|
40
|
+
end
|
41
|
+
|
42
|
+
before do
|
43
|
+
codec.stub(:encode) { |msg, _| msg }
|
44
|
+
end
|
45
|
+
|
46
|
+
before do
|
47
|
+
logger.stub(:info)
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#port' do
|
51
|
+
it 'returns the port the server is listening on' do
|
52
|
+
server.port.should == 4321
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#start' do
|
57
|
+
it 'starts the reactor' do
|
58
|
+
server.start.value
|
59
|
+
io_reactor.should have_received(:start)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'starts a server on the specified port' do
|
63
|
+
server.start.value
|
64
|
+
io_reactor.should have_received(:bind).with('0.0.0.0', 4321, 5)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'starts a server that binds to the specified address' do
|
68
|
+
server = described_class.new(4321, codec, io_reactor: io_reactor, bind_address: '1.1.1.1')
|
69
|
+
server.start.value
|
70
|
+
io_reactor.should have_received(:bind).with('1.1.1.1', 4321, anything)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'uses the specified queue size' do
|
74
|
+
server = described_class.new(4321, codec, io_reactor: io_reactor, queue_size: 11)
|
75
|
+
server.start.value
|
76
|
+
io_reactor.should have_received(:bind).with(anything, anything, 11)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'returns a future that resolves to the server' do
|
80
|
+
server.start.value.should equal(server)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'logs the address and port when listening for connections' do
|
84
|
+
server.start.value
|
85
|
+
logger.should have_received(:info).with('Server listening for connections on 0.0.0.0:4321')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#stop' do
|
90
|
+
it 'stops the reactor' do
|
91
|
+
server.stop.value
|
92
|
+
io_reactor.should have_received(:stop)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'returns a future that resolves to the server' do
|
96
|
+
server.stop.value.should equal(server)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
shared_context 'client_connections' do
|
101
|
+
let :accept_listeners do
|
102
|
+
[]
|
103
|
+
end
|
104
|
+
|
105
|
+
let :raw_connection do
|
106
|
+
double(:connection)
|
107
|
+
end
|
108
|
+
|
109
|
+
before do
|
110
|
+
raw_connection.stub(:on_data)
|
111
|
+
raw_connection.stub(:on_closed) { |&listener| raw_connection.stub(:closed_listener).and_return(listener) }
|
112
|
+
raw_connection.stub(:host).and_return('client.example.com')
|
113
|
+
raw_connection.stub(:port).and_return(34534)
|
114
|
+
raw_connection.stub(:write)
|
115
|
+
end
|
116
|
+
|
117
|
+
before do
|
118
|
+
acceptor.stub(:on_accept) do |&listener|
|
119
|
+
accept_listeners << listener
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
before do
|
124
|
+
server.start.value
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when a client connects' do
|
129
|
+
include_context 'client_connections'
|
130
|
+
|
131
|
+
before do
|
132
|
+
accept_listeners.first.call(raw_connection)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'calls #handle_connection with the client connection' do
|
136
|
+
server.connections.should have(1).item
|
137
|
+
server.connections.first.host.should == raw_connection.host
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'logs that a client connected' do
|
141
|
+
logger.should have_received(:info).with('Connection from client.example.com:34534 accepted')
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'logs when the client is disconnected' do
|
145
|
+
raw_connection.closed_listener.call
|
146
|
+
logger.should have_received(:info).with('Connection from client.example.com:34534 closed')
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when a client sends a request' do
|
151
|
+
include_context 'client_connections'
|
152
|
+
|
153
|
+
before do
|
154
|
+
accept_listeners.first.call(raw_connection)
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'calls #handle_request with the request' do
|
158
|
+
server.connections.first.handle_message('FOOBAZ', 42)
|
159
|
+
server.received_messages.first.should == ['FOOBAZ', server.connections.first]
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'responds to the same peer and channel when the future returned by #handle_request is resolved' do
|
163
|
+
promise = Promise.new
|
164
|
+
server.override_handle_request { promise.future }
|
165
|
+
peer = server.connections.first
|
166
|
+
peer.stub(:write_message)
|
167
|
+
peer.handle_message('FOOBAZ', 42)
|
168
|
+
peer.should_not have_received(:write_message)
|
169
|
+
promise.fulfill('BAZFOO')
|
170
|
+
peer.should have_received(:write_message).with('BAZFOO', 42)
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'uses the codec to encode the response' do
|
174
|
+
codec.stub(:encode).with('BAZFOO', 42).and_return('42BAZFOO')
|
175
|
+
server.override_handle_request { Future.resolved('BAZFOO') }
|
176
|
+
peer = server.connections.first
|
177
|
+
peer.handle_message('FOOBAZ', 42)
|
178
|
+
raw_connection.should have_received(:write).with('42BAZFOO')
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'handles that the server fails to process the request'
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
module ServerSpec
|
188
|
+
class TestServer < Ione::Rpc::Server
|
189
|
+
attr_reader :connections, :received_messages
|
190
|
+
|
191
|
+
def initialize(*)
|
192
|
+
super
|
193
|
+
@connections = []
|
194
|
+
@received_messages = []
|
195
|
+
end
|
196
|
+
|
197
|
+
def handle_connection(peer)
|
198
|
+
@connections << peer
|
199
|
+
end
|
200
|
+
|
201
|
+
def override_handle_request(&handler)
|
202
|
+
@request_handler = handler
|
203
|
+
end
|
204
|
+
|
205
|
+
def handle_request(request, peer)
|
206
|
+
@received_messages << [request, peer]
|
207
|
+
if @request_handler
|
208
|
+
@request_handler.call(request, peer)
|
209
|
+
else
|
210
|
+
super
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
ENV['SERVER_HOST'] ||= '127.0.0.1'.freeze
|
4
|
+
|
5
|
+
require 'bundler/setup'
|
6
|
+
|
7
|
+
unless ENV['COVERAGE'] == 'no' || RUBY_ENGINE == 'rbx'
|
8
|
+
require 'coveralls'
|
9
|
+
require 'simplecov'
|
10
|
+
|
11
|
+
if ENV.include?('TRAVIS')
|
12
|
+
Coveralls.wear!
|
13
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
14
|
+
end
|
15
|
+
|
16
|
+
SimpleCov.start do
|
17
|
+
add_group 'Source', 'lib'
|
18
|
+
add_group 'Unit tests', 'spec/ione'
|
19
|
+
add_group 'Integration tests', 'spec/integration'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'ione/rpc'
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ione-rpc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Theo Hultberg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ione
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
description: A toolkit for building RPC layers using Ione
|
28
|
+
email:
|
29
|
+
- theo@iconara.net
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .yardopts
|
35
|
+
- README.md
|
36
|
+
- lib/ione/rpc.rb
|
37
|
+
- lib/ione/rpc/client.rb
|
38
|
+
- lib/ione/rpc/client_peer.rb
|
39
|
+
- lib/ione/rpc/codec.rb
|
40
|
+
- lib/ione/rpc/peer.rb
|
41
|
+
- lib/ione/rpc/server.rb
|
42
|
+
- lib/ione/rpc/version.rb
|
43
|
+
- spec/ione/rpc/client_peer_spec.rb
|
44
|
+
- spec/ione/rpc/client_spec.rb
|
45
|
+
- spec/ione/rpc/codec_spec.rb
|
46
|
+
- spec/ione/rpc/peer_common.rb
|
47
|
+
- spec/ione/rpc/server_spec.rb
|
48
|
+
- spec/spec_helper.rb
|
49
|
+
homepage: http://github.com/iconara/ione-rpc
|
50
|
+
licenses:
|
51
|
+
- Apache License 2.0
|
52
|
+
metadata: {}
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.9.3
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - '>'
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 1.3.1
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 2.2.1
|
70
|
+
signing_key:
|
71
|
+
specification_version: 4
|
72
|
+
summary: RPC toolkit for Ruby
|
73
|
+
test_files:
|
74
|
+
- spec/ione/rpc/client_peer_spec.rb
|
75
|
+
- spec/ione/rpc/client_spec.rb
|
76
|
+
- spec/ione/rpc/codec_spec.rb
|
77
|
+
- spec/ione/rpc/peer_common.rb
|
78
|
+
- spec/ione/rpc/server_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
has_rdoc:
|