ione-rpc 1.0.0.pre0
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.
- 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:
|