arpie 0.0.4 → 0.0.5
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/BINARY_SPEC +218 -0
- data/README +46 -0
- data/Rakefile +2 -2
- data/lib/arpie/binary.rb +754 -0
- data/lib/arpie/error.rb +39 -0
- data/lib/arpie/protocol.rb +103 -106
- data/lib/arpie/xmlrpc.rb +4 -4
- data/lib/arpie.rb +2 -0
- data/spec/protocol_merge_and_split_spec.rb +28 -8
- data/spec/protocol_spec.rb +4 -0
- metadata +12 -8
data/lib/arpie/error.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Arpie
|
2
|
+
|
3
|
+
# Raised by arpie when a Protocol thinks the stream got corrupted
|
4
|
+
# (by calling bogon!).
|
5
|
+
# This usually results in a dropped connection.
|
6
|
+
class StreamError < IOError ; end
|
7
|
+
# Raised by arpie when a Protocol needs more data to parse a packet.
|
8
|
+
# Usually only of relevance to the programmer when using Protocol#from directly.
|
9
|
+
class EIncomplete < RuntimeError ; end
|
10
|
+
|
11
|
+
# :stopdoc:
|
12
|
+
# Used internally by arpie.
|
13
|
+
class ETryAgain < RuntimeError ; end
|
14
|
+
class YieldResult < RuntimeError
|
15
|
+
attr_reader :result
|
16
|
+
def initialize result
|
17
|
+
@result = result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
# :startdoc:
|
21
|
+
|
22
|
+
# Call this if you think the stream has been corrupted, or
|
23
|
+
# non-protocol data arrived.
|
24
|
+
# +message+ is the text to display.
|
25
|
+
# +data+ is the optional misbehaving data for printing.
|
26
|
+
# This breaks out of the caller.
|
27
|
+
def bogon! data = nil, message = nil
|
28
|
+
raise StreamError, "#{self.is_a?(Class) ? self.to_s : self.class.to_s}:" +
|
29
|
+
" BOGON#{data.nil? ? "" : " " + data.inspect}" +
|
30
|
+
"#{message.nil? ? "" : " -- #{message}" }"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Tell the caller that the given chunk of data
|
34
|
+
# is not enough to construct a whole message.
|
35
|
+
# This breaks out of the caller.
|
36
|
+
def incomplete!
|
37
|
+
raise EIncomplete, "#{self.is_a?(Class) ? self : self.class} needs more data"
|
38
|
+
end
|
39
|
+
end
|
data/lib/arpie/protocol.rb
CHANGED
@@ -1,28 +1,9 @@
|
|
1
1
|
require 'shellwords'
|
2
2
|
require 'yaml'
|
3
|
+
require 'zlib'
|
3
4
|
|
4
5
|
module Arpie
|
5
6
|
MTU = 1024
|
6
|
-
# Raised by arpie when a Protocol thinks the stream got corrupted
|
7
|
-
# (by calling stream_error!).
|
8
|
-
# This usually results in a dropped connection.
|
9
|
-
class StreamError < IOError ; end
|
10
|
-
# Raised by arpie when a Protocol needs more data to parse a packet.
|
11
|
-
# Usually only of relevance to the programmer when using Protocol#from directly.
|
12
|
-
class EIncomplete < RuntimeError ; end
|
13
|
-
|
14
|
-
# :stopdoc:
|
15
|
-
# Used internally by arpie.
|
16
|
-
class ESwallow < RuntimeError ; end
|
17
|
-
class ETryAgain < RuntimeError ; end
|
18
|
-
class YieldResult < RuntimeError
|
19
|
-
attr_reader :result
|
20
|
-
def initialize result
|
21
|
-
@result = result
|
22
|
-
end
|
23
|
-
end
|
24
|
-
# :startdoc:
|
25
|
-
|
26
7
|
# A RPC call. You need to wrap all calls sent over RPC protocols in this.
|
27
8
|
class RPCall < Struct.new(:ns, :meth, :argv, :uuid); end
|
28
9
|
|
@@ -30,6 +11,7 @@ module Arpie
|
|
30
11
|
# list, into which io data can be fed and parsed packets received; and
|
31
12
|
# vice versa.
|
32
13
|
class ProtocolChain
|
14
|
+
include Arpie
|
33
15
|
|
34
16
|
# Array of Protocols.
|
35
17
|
attr_reader :chain
|
@@ -67,9 +49,18 @@ module Arpie
|
|
67
49
|
# Convert the given +message+ to wire format by
|
68
50
|
# passing it through all protocols in the chain.
|
69
51
|
def to message
|
70
|
-
|
71
|
-
|
52
|
+
messages = [message]
|
53
|
+
@chain.each {|p|
|
54
|
+
for_next = []
|
55
|
+
messages.each {|msg|
|
56
|
+
p.to(msg) do |a|
|
57
|
+
for_next << a
|
58
|
+
end
|
59
|
+
}
|
60
|
+
|
61
|
+
messages = for_next
|
72
62
|
}
|
63
|
+
messages
|
73
64
|
end
|
74
65
|
|
75
66
|
# Convert the given +binary+ to message format
|
@@ -106,56 +97,54 @@ module Arpie
|
|
106
97
|
cut_to_index = nil
|
107
98
|
messages_for_next = []
|
108
99
|
|
109
|
-
messages.
|
100
|
+
messages.each_with_index do |message, m_index|
|
110
101
|
cut_to_index = p.from(message) do |object|
|
111
102
|
messages_for_next << object
|
112
103
|
end rescue case $!
|
113
|
-
|
114
104
|
when YieldResult
|
115
105
|
messages_for_next.concat($!.result)
|
116
106
|
next
|
117
107
|
|
118
|
-
when ESwallow
|
119
|
-
messages.delete(message)
|
120
|
-
messages_for_next = messages
|
121
|
-
p_index -= 1
|
122
|
-
break
|
123
|
-
|
124
108
|
when EIncomplete
|
125
|
-
|
126
|
-
|
127
|
-
if p_index > 0
|
128
|
-
# Unwind to the parent protocol and let it read in some
|
129
|
-
# more messages ..
|
130
|
-
messages_for_next = messages
|
131
|
-
messages_for_next.shift
|
132
|
-
p_index -= 1
|
133
|
-
break
|
134
|
-
|
135
|
-
# The first protocol manages +io+.
|
109
|
+
if messages.size - 1 - m_index > 0
|
110
|
+
next
|
136
111
|
else
|
137
|
-
|
138
|
-
@buffer << io.readpartial(MTU) rescue raise $!.class,
|
139
|
-
"#{$!.to_s}; unparseable bytes remaining in buffer: #{@buffer.size}"
|
140
|
-
retry
|
112
|
+
raise
|
141
113
|
end
|
142
114
|
|
143
|
-
|
115
|
+
else
|
116
|
+
raise
|
117
|
+
end
|
118
|
+
end rescue case $!
|
119
|
+
when EIncomplete
|
120
|
+
if p_index == 0
|
121
|
+
select([io])
|
122
|
+
@buffer << io.readpartial(MTU) rescue raise $!.class,
|
123
|
+
"#{$!.to_s}; unparseable bytes remaining in buffer: #{@buffer.size}"
|
144
124
|
retry
|
145
125
|
|
146
126
|
else
|
147
|
-
|
148
|
-
|
149
|
-
|
127
|
+
p_index = 0
|
128
|
+
messages_for_next = []
|
129
|
+
messages = [@buffer]
|
130
|
+
next # of loop protocol chain
|
131
|
+
end
|
150
132
|
|
151
|
-
|
152
|
-
|
133
|
+
else
|
134
|
+
raise
|
135
|
+
end
|
136
|
+
|
137
|
+
if messages_for_next.size == 0
|
138
|
+
# Get back to IO level and retry reading more crud
|
139
|
+
messages_for_next = [@buffer]
|
140
|
+
p_index = -1
|
141
|
+
end
|
153
142
|
|
154
143
|
messages = messages_for_next
|
155
144
|
|
156
145
|
if p_index == 0
|
157
146
|
if cut_to_index.nil? || cut_to_index < 0
|
158
|
-
raise "Protocol '#{p.class.to_s}'implementation faulty: " +
|
147
|
+
raise "Protocol '#{p.class.to_s}' implementation faulty: " +
|
159
148
|
"from did return an invalid cut index: #{cut_to_index.inspect}."
|
160
149
|
else
|
161
150
|
@buffer[0, cut_to_index] = ""
|
@@ -163,16 +152,18 @@ module Arpie
|
|
163
152
|
end
|
164
153
|
|
165
154
|
p_index += 1
|
166
|
-
end # chain
|
155
|
+
end # loop chain
|
167
156
|
|
168
157
|
message = messages.shift
|
169
158
|
@messages = messages
|
170
159
|
message
|
171
160
|
end
|
172
161
|
|
162
|
+
|
173
163
|
# Write +message+ to +io+.
|
174
|
-
def write_message io,
|
175
|
-
|
164
|
+
def write_message io, *messages
|
165
|
+
binary = messages.map {|m| to(m)}
|
166
|
+
io.write(binary)
|
176
167
|
end
|
177
168
|
|
178
169
|
def reset
|
@@ -183,17 +174,25 @@ module Arpie
|
|
183
174
|
# A Protocol converts messages (which are arbitary objects)
|
184
175
|
# to a suitable on-the-wire format, and back.
|
185
176
|
class Protocol
|
177
|
+
include Arpie
|
186
178
|
|
187
179
|
# Set this to true in child classes which implement
|
188
180
|
# message separation within a stream.
|
189
181
|
CAN_SEPARATE_MESSAGES = false
|
190
182
|
|
183
|
+
# :stopdoc:
|
184
|
+
# The stowbuffer hash used by assemble! No need to touch this, usually.
|
185
|
+
attr_reader :stowbuffer
|
186
|
+
# The meta-information hash used by assemble! No need to touch this, usually.
|
187
|
+
attr_reader :metabuffer
|
188
|
+
# :startdoc:
|
189
|
+
|
191
190
|
# Convert obj to on-the-wire format.
|
192
191
|
def to obj
|
193
|
-
obj
|
192
|
+
yield obj
|
194
193
|
end
|
195
194
|
|
196
|
-
# Extract message(s) from +binary+.
|
195
|
+
# Extract message(s) from +binary+.
|
197
196
|
#
|
198
197
|
# Yields each message found, with all protocol-specifics stripped.
|
199
198
|
#
|
@@ -219,74 +218,55 @@ module Arpie
|
|
219
218
|
raise ETryAgain
|
220
219
|
end
|
221
220
|
|
222
|
-
# Tell the protocol chain that the given chunk of data
|
223
|
-
# is not enough to construct a whole message.
|
224
|
-
# This breaks out of Protocol#from.
|
225
|
-
def incomplete!
|
226
|
-
raise EIncomplete
|
227
|
-
end
|
228
|
-
|
229
|
-
# Swallow the complete message currently passed to Protocol#from.
|
230
|
-
# Not advised for the outermost protocol, which works on io buffer streams
|
231
|
-
# and may swallow more than intended.
|
232
|
-
def gulp!
|
233
|
-
raise ESwallow
|
234
|
-
end
|
235
|
-
alias_method :swallow!, :gulp!
|
236
|
-
|
237
221
|
# Stow away a message in this protocols buffer for later reassembly.
|
238
222
|
# Optional argument: a token if you are planning to reassemble multiple
|
239
223
|
# interleaved/fragmented message streams.
|
240
224
|
#
|
225
|
+
# If you pass a block, that block will be called; if no block is given,
|
226
|
+
# Protocol#assemble will be invoked.
|
227
|
+
#
|
228
|
+
# Any leftover binaries passed into assemble! that get not returned in
|
229
|
+
# the assembler will be discarded; they are assumed to be syntax or framework.
|
230
|
+
#
|
241
231
|
# +binary+ is the binary packet you want to add to the assembly
|
242
|
-
# +token+ is a object which can be used to
|
232
|
+
# +token+ is a object which can be used to identify multiple concurrent assemblies (think Hash.keys)
|
243
233
|
# +meta+ is a hash containing meta-information for this assembly
|
244
234
|
# each call to assemble! will merge these hashes, and pass them
|
245
235
|
# on to Protocol#assemble
|
246
|
-
def assemble! binary, token = :default, meta = {}
|
236
|
+
def assemble! binary, token = :default, meta = {} # :yields: binaries, metadata
|
247
237
|
@stowbuffer ||= {}
|
248
238
|
@stowbuffer[token] ||= []
|
249
239
|
@stowbuffer[token] << binary
|
250
240
|
|
251
241
|
@metabuffer ||= {}
|
252
242
|
@metabuffer[token] ||= {}
|
253
|
-
@metabuffer[token].merge(meta)
|
254
|
-
|
255
|
-
assembled =
|
256
|
-
|
257
|
-
|
258
|
-
assembled
|
259
|
-
|
260
|
-
|
261
|
-
#
|
262
|
-
#
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
raise YieldResult, assembled
|
243
|
+
@metabuffer[token].merge!(meta)
|
244
|
+
|
245
|
+
assembled = nil
|
246
|
+
|
247
|
+
if block_given?
|
248
|
+
assembled = yield(@stowbuffer[token], @metabuffer[token])
|
249
|
+
|
250
|
+
else
|
251
|
+
# This raises EIncomplete when not enough messages are there,
|
252
|
+
# and passes it straight on to #read_message
|
253
|
+
assembled = assemble(@stowbuffer[token], @metabuffer[token])
|
254
|
+
end
|
255
|
+
|
256
|
+
@stowbuffer.delete(token)
|
257
|
+
@metabuffer.delete(token)
|
258
|
+
raise YieldResult, [assembled]
|
269
259
|
end
|
270
260
|
|
271
261
|
# Called when we're trying to reassemble a stream of packets.
|
272
262
|
#
|
273
263
|
# Call incomplete! when not enough data is here to reassemble this stream,
|
274
264
|
# and yield all results of the reassembled stream.
|
275
|
-
def assemble binaries,
|
265
|
+
def assemble binaries, meta
|
276
266
|
raise NotImplementedError, "Tried to assemble! something, but no assembler defined."
|
277
267
|
end
|
278
|
-
|
279
|
-
# Call this if you think the stream has been corrupted, or
|
280
|
-
# non-protocol data arrived.
|
281
|
-
# +message+ is the text to display.
|
282
|
-
# +data+ is the optional misbehaving data for printing.
|
283
|
-
# This breaks out of Protocol#from.
|
284
|
-
def bogon! data = nil, message = nil
|
285
|
-
raise StreamError, "#{self.class.to_s}#{message.nil? ? " thinks the data is bogus" : ": " + message }#{data.nil? ? "" : ": " + data.inspect}."
|
286
|
-
end
|
287
268
|
end
|
288
269
|
|
289
|
-
|
290
270
|
# A sample binary protocol, which simply prefixes each message with the
|
291
271
|
# size of the data to be expected.
|
292
272
|
class SizedProtocol < Protocol
|
@@ -300,7 +280,7 @@ module Arpie
|
|
300
280
|
end
|
301
281
|
|
302
282
|
def to object
|
303
|
-
[object.size, object].pack('Qa*')
|
283
|
+
yield [object.size, object].pack('Qa*')
|
304
284
|
end
|
305
285
|
end
|
306
286
|
|
@@ -310,7 +290,7 @@ module Arpie
|
|
310
290
|
# Messages are arbitary objects.
|
311
291
|
class MarshalProtocol < Protocol
|
312
292
|
def to object
|
313
|
-
Marshal.dump(object)
|
293
|
+
yield Marshal.dump(object)
|
314
294
|
end
|
315
295
|
|
316
296
|
def from binary
|
@@ -336,7 +316,7 @@ module Arpie
|
|
336
316
|
end
|
337
317
|
|
338
318
|
def to object
|
339
|
-
object.to_s + @separator
|
319
|
+
yield object.to_s + @separator
|
340
320
|
end
|
341
321
|
end
|
342
322
|
|
@@ -347,7 +327,7 @@ module Arpie
|
|
347
327
|
def to object
|
348
328
|
raise ArgumentError, "#{self.class.to_s} can only encode arrays." unless
|
349
329
|
object.is_a?(Array)
|
350
|
-
Shellwords.join(object.map {|x| x.to_s })
|
330
|
+
yield Shellwords.join(object.map {|x| x.to_s })
|
351
331
|
end
|
352
332
|
|
353
333
|
def from binary
|
@@ -361,7 +341,7 @@ module Arpie
|
|
361
341
|
CAN_SEPARATE_MESSAGES = true
|
362
342
|
|
363
343
|
def to object
|
364
|
-
YAML.dump(object) + "...\n"
|
344
|
+
yield YAML.dump(object) + "...\n"
|
365
345
|
end
|
366
346
|
|
367
347
|
def from binary
|
@@ -370,4 +350,21 @@ module Arpie
|
|
370
350
|
4 + index
|
371
351
|
end
|
372
352
|
end
|
353
|
+
|
354
|
+
# A transparent zlib stream de/compression protocol.
|
355
|
+
class ZlibProtocol < Protocol
|
356
|
+
def initialize
|
357
|
+
@inflater = Zlib::Inflate.new
|
358
|
+
@deflater = Zlib::Deflate.new
|
359
|
+
end
|
360
|
+
|
361
|
+
def to object
|
362
|
+
yield @deflater.deflate(object) + @deflater.flush
|
363
|
+
end
|
364
|
+
|
365
|
+
def from binary
|
366
|
+
yield @inflater.inflate(binary)
|
367
|
+
binary.size
|
368
|
+
end
|
369
|
+
end
|
373
370
|
end
|
data/lib/arpie/xmlrpc.rb
CHANGED
@@ -29,7 +29,7 @@ module Arpie
|
|
29
29
|
raise ArgumentError, "Can only encode Arpie::RPCall" unless
|
30
30
|
object.is_a?(Arpie::RPCall)
|
31
31
|
|
32
|
-
@writer.methodCall((object.ns.nil? ? '' : object.ns + '.') + object.meth, *object.argv)
|
32
|
+
yield @writer.methodCall((object.ns.nil? ? '' : object.ns + '.') + object.meth, *object.argv)
|
33
33
|
end
|
34
34
|
|
35
35
|
def from binary
|
@@ -43,7 +43,7 @@ module Arpie
|
|
43
43
|
|
44
44
|
def to object
|
45
45
|
setup
|
46
|
-
case object
|
46
|
+
yield case object
|
47
47
|
when Exception
|
48
48
|
# TODO: wrap XMLFault
|
49
49
|
raise NotImplementedError, "Cannot encode exceptions"
|
@@ -93,7 +93,7 @@ module Arpie
|
|
93
93
|
public_class_method :new
|
94
94
|
|
95
95
|
def to object
|
96
|
-
"GET / HTTP/1.[01]\r\nContent-Length: #{object.size}\r\n\r\n" + object
|
96
|
+
yield "GET / HTTP/1.[01]\r\nContent-Length: #{object.size}\r\n\r\n" + object
|
97
97
|
end
|
98
98
|
|
99
99
|
end
|
@@ -102,7 +102,7 @@ module Arpie
|
|
102
102
|
public_class_method :new
|
103
103
|
|
104
104
|
def to object
|
105
|
-
"HTTP/1.0 200 OK\r\nContent-Length: #{object.size}\r\n\r\n" + object
|
105
|
+
yield "HTTP/1.0 200 OK\r\nContent-Length: #{object.size}\r\n\r\n" + object
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
data/lib/arpie.rb
CHANGED
@@ -3,25 +3,35 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
3
3
|
class Splitter < Arpie::Protocol
|
4
4
|
def from binary
|
5
5
|
yield binary.size
|
6
|
+
|
6
7
|
binary.each_char do |c|
|
7
8
|
yield c
|
8
9
|
end
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
12
|
-
class
|
13
|
+
class BufferedSplitter < Arpie::Protocol
|
13
14
|
def from binary
|
14
|
-
unless @
|
15
|
-
|
16
|
-
|
15
|
+
unless defined? @buf
|
16
|
+
yield binary.size * 2
|
17
|
+
@buf = true
|
17
18
|
end
|
18
19
|
|
19
|
-
|
20
|
+
binary.each_char do |c|
|
21
|
+
yield c
|
22
|
+
end
|
20
23
|
end
|
24
|
+
end
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
|
27
|
+
class Merger < Arpie::Protocol
|
28
|
+
def from binary
|
29
|
+
assemble! binary do |binaries, meta|
|
30
|
+
binaries.size >= 1 or incomplete!
|
31
|
+
binaries.size - 1 >= binaries[0].to_i or incomplete!
|
32
|
+
binaries.shift
|
33
|
+
binaries.join('')
|
34
|
+
end
|
25
35
|
end
|
26
36
|
end
|
27
37
|
|
@@ -45,3 +55,13 @@ describe "Merger::Splitter::Sized" do subject { [Merger, Splitter, Arpie::SizedP
|
|
45
55
|
chain_read.should == t
|
46
56
|
end
|
47
57
|
end
|
58
|
+
|
59
|
+
describe "Merger::BufferedSplitter::Sized" do subject { [Merger, BufferedSplitter, Arpie::SizedProtocol] }
|
60
|
+
it_should_behave_like "ProtocolChainSetup"
|
61
|
+
|
62
|
+
it "should re-read io for more data if assembly fails" do
|
63
|
+
@chain.write_message(@w, "split")
|
64
|
+
Thread.new { sleep 0.1; @chain.write_message(@w, "split") }
|
65
|
+
chain_read.should == "splitsplit"
|
66
|
+
end
|
67
|
+
end
|
data/spec/protocol_spec.rb
CHANGED
@@ -112,6 +112,10 @@ describe "Sized::Marshal::Sized" do subject { [Arpie::SizedProtocol, Arpie::Mars
|
|
112
112
|
it_should_behave_like "ProtocolChain"
|
113
113
|
end
|
114
114
|
|
115
|
+
describe "Zlib::Marshal::Sized" do subject { [Arpie::ZlibProtocol, Arpie::MarshalProtocol, Arpie::SizedProtocol] }
|
116
|
+
it_should_behave_like "ProtocolChain"
|
117
|
+
end
|
118
|
+
|
115
119
|
# Shellwords is a bit of a special case, because it only encodes arrays.
|
116
120
|
describe "Shellwords::Separator" do subject { [Arpie::ShellwordsProtocol, Arpie::SeparatorProtocol] }
|
117
121
|
it_should_behave_like "ProtocolChain"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arpie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernhard Stoeckner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-24 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -31,25 +31,29 @@ extensions: []
|
|
31
31
|
extra_rdoc_files:
|
32
32
|
- README
|
33
33
|
- COPYING
|
34
|
+
- BINARY_SPEC
|
34
35
|
files:
|
35
36
|
- COPYING
|
36
37
|
- README
|
37
38
|
- Rakefile
|
38
|
-
- spec/rcov.opts
|
39
|
-
- spec/protocol_merge_and_split_spec.rb
|
40
|
-
- spec/spec_helper.rb
|
41
39
|
- spec/protocol_spec.rb
|
42
40
|
- spec/spec.opts
|
41
|
+
- spec/spec_helper.rb
|
42
|
+
- spec/protocol_merge_and_split_spec.rb
|
43
|
+
- spec/rcov.opts
|
43
44
|
- spec/client_server_spec.rb
|
45
|
+
- lib/arpie.rb
|
44
46
|
- lib/arpie
|
45
|
-
- lib/arpie/proxy.rb
|
46
|
-
- lib/arpie/xmlrpc.rb
|
47
47
|
- lib/arpie/client.rb
|
48
|
+
- lib/arpie/error.rb
|
48
49
|
- lib/arpie/protocol.rb
|
50
|
+
- lib/arpie/binary.rb
|
51
|
+
- lib/arpie/proxy.rb
|
52
|
+
- lib/arpie/xmlrpc.rb
|
49
53
|
- lib/arpie/server.rb
|
50
|
-
- lib/arpie.rb
|
51
54
|
- tools/benchmark.rb
|
52
55
|
- tools/protocol_benchmark.rb
|
56
|
+
- BINARY_SPEC
|
53
57
|
has_rdoc: true
|
54
58
|
homepage: http://arpie.elv.es
|
55
59
|
post_install_message:
|