rubysl-net-protocol 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/net/protocol.rb +1 -0
- data/lib/rubysl/net/protocol.rb +2 -0
- data/lib/rubysl/net/protocol/protocol.rb +392 -0
- data/lib/rubysl/net/protocol/version.rb +7 -0
- data/rubysl-net-protocol.gemspec +21 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7a5f5190a2f8eea39f80416cc303533647f25b1c
|
4
|
+
data.tar.gz: e7e39d163a97f4f42b9f1da93968fc84729d41a2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c451315d4c840b290f1adee071288a5eaf9b65638090c649ed7c87d8813ddc0ca4fd5f43251b0ffd122a2148ebb12442899ae26d73b93f8ee9a92ab2d7fc9d67
|
7
|
+
data.tar.gz: 78b3ae013cadd203836a021c62f5f4c5410b143e6bfcfd4eb36fb0eeb679ea28ff159fa2eb9d1da3d23741830b254aeaa9a9ff28440678463318160c8e6a71dc
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2013, Brian Shirai
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
3. Neither the name of the library nor the names of its contributors may be
|
13
|
+
used to endorse or promote products derived from this software without
|
14
|
+
specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
|
20
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
21
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
22
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
23
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
24
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
25
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Rubysl::Net::Protocol
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rubysl-net-protocol'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rubysl-net-protocol
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/net/protocol.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "rubysl/net/protocol"
|
@@ -0,0 +1,392 @@
|
|
1
|
+
#
|
2
|
+
# = net/protocol.rb
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
# Copyright (c) 1999-2005 Yukihiro Matsumoto
|
6
|
+
# Copyright (c) 1999-2005 Minero Aoki
|
7
|
+
#
|
8
|
+
# written and maintained by Minero Aoki <aamine@loveruby.net>
|
9
|
+
#
|
10
|
+
# This program is free software. You can re-distribute and/or
|
11
|
+
# modify this program under the same terms as Ruby itself,
|
12
|
+
# Ruby Distribute License or GNU General Public License.
|
13
|
+
#
|
14
|
+
# $Id$
|
15
|
+
#++
|
16
|
+
#
|
17
|
+
# WARNING: This file is going to remove.
|
18
|
+
# Do not rely on the implementation written in this file.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'socket'
|
22
|
+
require 'timeout'
|
23
|
+
|
24
|
+
module Net # :nodoc:
|
25
|
+
|
26
|
+
class Protocol #:nodoc: internal use only
|
27
|
+
private
|
28
|
+
def Protocol.protocol_param(name, val)
|
29
|
+
module_eval(<<-End, __FILE__, __LINE__ + 1)
|
30
|
+
def #{name}
|
31
|
+
#{val}
|
32
|
+
end
|
33
|
+
End
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
class ProtocolError < StandardError; end
|
39
|
+
class ProtoSyntaxError < ProtocolError; end
|
40
|
+
class ProtoFatalError < ProtocolError; end
|
41
|
+
class ProtoUnknownError < ProtocolError; end
|
42
|
+
class ProtoServerError < ProtocolError; end
|
43
|
+
class ProtoAuthError < ProtocolError; end
|
44
|
+
class ProtoCommandError < ProtocolError; end
|
45
|
+
class ProtoRetriableError < ProtocolError; end
|
46
|
+
ProtocRetryError = ProtoRetriableError
|
47
|
+
|
48
|
+
|
49
|
+
class BufferedIO #:nodoc: internal use only
|
50
|
+
def initialize(io)
|
51
|
+
@io = io
|
52
|
+
@read_timeout = 60
|
53
|
+
@debug_output = nil
|
54
|
+
@rbuf = ''
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :io
|
58
|
+
attr_accessor :read_timeout
|
59
|
+
attr_accessor :debug_output
|
60
|
+
|
61
|
+
def inspect
|
62
|
+
"#<#{self.class} io=#{@io}>"
|
63
|
+
end
|
64
|
+
|
65
|
+
def closed?
|
66
|
+
@io.closed?
|
67
|
+
end
|
68
|
+
|
69
|
+
def close
|
70
|
+
@io.close
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Read
|
75
|
+
#
|
76
|
+
|
77
|
+
public
|
78
|
+
|
79
|
+
def read(len, dest = '', ignore_eof = false)
|
80
|
+
LOG "reading #{len} bytes..."
|
81
|
+
read_bytes = 0
|
82
|
+
begin
|
83
|
+
while read_bytes + @rbuf.size < len
|
84
|
+
dest << (s = rbuf_consume(@rbuf.size))
|
85
|
+
read_bytes += s.size
|
86
|
+
rbuf_fill
|
87
|
+
end
|
88
|
+
dest << (s = rbuf_consume(len - read_bytes))
|
89
|
+
read_bytes += s.size
|
90
|
+
rescue EOFError
|
91
|
+
raise unless ignore_eof
|
92
|
+
end
|
93
|
+
LOG "read #{read_bytes} bytes"
|
94
|
+
dest
|
95
|
+
end
|
96
|
+
|
97
|
+
def read_all(dest = '')
|
98
|
+
LOG 'reading all...'
|
99
|
+
read_bytes = 0
|
100
|
+
begin
|
101
|
+
while true
|
102
|
+
dest << (s = rbuf_consume(@rbuf.size))
|
103
|
+
read_bytes += s.size
|
104
|
+
rbuf_fill
|
105
|
+
end
|
106
|
+
rescue EOFError
|
107
|
+
;
|
108
|
+
end
|
109
|
+
LOG "read #{read_bytes} bytes"
|
110
|
+
dest
|
111
|
+
end
|
112
|
+
|
113
|
+
def readuntil(terminator, ignore_eof = false)
|
114
|
+
begin
|
115
|
+
until idx = @rbuf.index(terminator)
|
116
|
+
rbuf_fill
|
117
|
+
end
|
118
|
+
return rbuf_consume(idx + terminator.size)
|
119
|
+
rescue EOFError
|
120
|
+
raise unless ignore_eof
|
121
|
+
return rbuf_consume(@rbuf.size)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def readline
|
126
|
+
readuntil("\n").chop
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
BUFSIZE = 1024 * 16
|
132
|
+
|
133
|
+
def rbuf_fill
|
134
|
+
timeout(@read_timeout) {
|
135
|
+
@rbuf << @io.sysread(BUFSIZE)
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
def rbuf_consume(len)
|
140
|
+
s = @rbuf.slice!(0, len)
|
141
|
+
@debug_output << %Q[-> #{s.dump}\n] if @debug_output
|
142
|
+
s
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# Write
|
147
|
+
#
|
148
|
+
|
149
|
+
public
|
150
|
+
|
151
|
+
def write(str)
|
152
|
+
writing {
|
153
|
+
write0 str
|
154
|
+
}
|
155
|
+
end
|
156
|
+
|
157
|
+
def writeline(str)
|
158
|
+
writing {
|
159
|
+
write0 str + "\r\n"
|
160
|
+
}
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def writing
|
166
|
+
@written_bytes = 0
|
167
|
+
@debug_output << '<- ' if @debug_output
|
168
|
+
yield
|
169
|
+
@debug_output << "\n" if @debug_output
|
170
|
+
bytes = @written_bytes
|
171
|
+
@written_bytes = nil
|
172
|
+
bytes
|
173
|
+
end
|
174
|
+
|
175
|
+
def write0(str)
|
176
|
+
@debug_output << str.dump if @debug_output
|
177
|
+
len = @io.write(str)
|
178
|
+
@written_bytes += len
|
179
|
+
len
|
180
|
+
end
|
181
|
+
|
182
|
+
#
|
183
|
+
# Logging
|
184
|
+
#
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def LOG_off
|
189
|
+
@save_debug_out = @debug_output
|
190
|
+
@debug_output = nil
|
191
|
+
end
|
192
|
+
|
193
|
+
def LOG_on
|
194
|
+
@debug_output = @save_debug_out
|
195
|
+
end
|
196
|
+
|
197
|
+
def LOG(msg)
|
198
|
+
return unless @debug_output
|
199
|
+
@debug_output << msg + "\n"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
class InternetMessageIO < BufferedIO #:nodoc: internal use only
|
205
|
+
def InternetMessageIO.old_open(addr, port,
|
206
|
+
open_timeout = nil, read_timeout = nil, debug_output = nil)
|
207
|
+
debug_output << "opening connection to #{addr}...\n" if debug_output
|
208
|
+
s = timeout(open_timeout) { TCPsocket.new(addr, port) }
|
209
|
+
io = new(s)
|
210
|
+
io.read_timeout = read_timeout
|
211
|
+
io.debug_output = debug_output
|
212
|
+
io
|
213
|
+
end
|
214
|
+
|
215
|
+
def initialize(io)
|
216
|
+
super
|
217
|
+
@wbuf = nil
|
218
|
+
end
|
219
|
+
|
220
|
+
#
|
221
|
+
# Read
|
222
|
+
#
|
223
|
+
|
224
|
+
def each_message_chunk
|
225
|
+
LOG 'reading message...'
|
226
|
+
LOG_off()
|
227
|
+
read_bytes = 0
|
228
|
+
while (line = readuntil("\r\n")) != ".\r\n"
|
229
|
+
read_bytes += line.size
|
230
|
+
yield line.sub(/\A\./, '')
|
231
|
+
end
|
232
|
+
LOG_on()
|
233
|
+
LOG "read message (#{read_bytes} bytes)"
|
234
|
+
end
|
235
|
+
|
236
|
+
# *library private* (cannot handle 'break')
|
237
|
+
def each_list_item
|
238
|
+
while (str = readuntil("\r\n")) != ".\r\n"
|
239
|
+
yield str.chop
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def write_message_0(src)
|
244
|
+
prev = @written_bytes
|
245
|
+
each_crlf_line(src) do |line|
|
246
|
+
write0 line.sub(/\A\./, '..')
|
247
|
+
end
|
248
|
+
@written_bytes - prev
|
249
|
+
end
|
250
|
+
|
251
|
+
#
|
252
|
+
# Write
|
253
|
+
#
|
254
|
+
|
255
|
+
def write_message(src)
|
256
|
+
LOG "writing message from #{src.class}"
|
257
|
+
LOG_off()
|
258
|
+
len = writing {
|
259
|
+
using_each_crlf_line {
|
260
|
+
write_message_0 src
|
261
|
+
}
|
262
|
+
}
|
263
|
+
LOG_on()
|
264
|
+
LOG "wrote #{len} bytes"
|
265
|
+
len
|
266
|
+
end
|
267
|
+
|
268
|
+
def write_message_by_block(&block)
|
269
|
+
LOG 'writing message from block'
|
270
|
+
LOG_off()
|
271
|
+
len = writing {
|
272
|
+
using_each_crlf_line {
|
273
|
+
begin
|
274
|
+
block.call(WriteAdapter.new(self, :write_message_0))
|
275
|
+
rescue LocalJumpError
|
276
|
+
# allow `break' from writer block
|
277
|
+
end
|
278
|
+
}
|
279
|
+
}
|
280
|
+
LOG_on()
|
281
|
+
LOG "wrote #{len} bytes"
|
282
|
+
len
|
283
|
+
end
|
284
|
+
|
285
|
+
private
|
286
|
+
|
287
|
+
def using_each_crlf_line
|
288
|
+
@wbuf = ''
|
289
|
+
yield
|
290
|
+
if not @wbuf.empty? # unterminated last line
|
291
|
+
write0 @wbuf.chomp + "\r\n"
|
292
|
+
elsif @written_bytes == 0 # empty src
|
293
|
+
write0 "\r\n"
|
294
|
+
end
|
295
|
+
write0 ".\r\n"
|
296
|
+
@wbuf = nil
|
297
|
+
end
|
298
|
+
|
299
|
+
def each_crlf_line(src)
|
300
|
+
buffer_filling(@wbuf, src) do
|
301
|
+
while line = @wbuf.slice!(/\A.*(?:\n|\r\n|\r(?!\z))/n)
|
302
|
+
yield line.chomp("\n") + "\r\n"
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def buffer_filling(buf, src)
|
308
|
+
case src
|
309
|
+
when String # for speeding up.
|
310
|
+
0.step(src.size - 1, 1024) do |i|
|
311
|
+
buf << src[i, 1024]
|
312
|
+
yield
|
313
|
+
end
|
314
|
+
when File # for speeding up.
|
315
|
+
while s = src.read(1024)
|
316
|
+
buf << s
|
317
|
+
yield
|
318
|
+
end
|
319
|
+
else # generic reader
|
320
|
+
src.each do |s|
|
321
|
+
buf << s
|
322
|
+
yield if buf.size > 1024
|
323
|
+
end
|
324
|
+
yield unless buf.empty?
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
#
|
331
|
+
# The writer adapter class
|
332
|
+
#
|
333
|
+
class WriteAdapter
|
334
|
+
def initialize(socket, method)
|
335
|
+
@socket = socket
|
336
|
+
@method_id = method
|
337
|
+
end
|
338
|
+
|
339
|
+
def inspect
|
340
|
+
"#<#{self.class} socket=#{@socket.inspect}>"
|
341
|
+
end
|
342
|
+
|
343
|
+
def write(str)
|
344
|
+
@socket.__send__(@method_id, str)
|
345
|
+
end
|
346
|
+
|
347
|
+
alias print write
|
348
|
+
|
349
|
+
def <<(str)
|
350
|
+
write str
|
351
|
+
self
|
352
|
+
end
|
353
|
+
|
354
|
+
def puts(str = '')
|
355
|
+
write str.chomp("\n") + "\n"
|
356
|
+
end
|
357
|
+
|
358
|
+
def printf(*args)
|
359
|
+
write sprintf(*args)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
|
364
|
+
class ReadAdapter #:nodoc: internal use only
|
365
|
+
def initialize(block)
|
366
|
+
@block = block
|
367
|
+
end
|
368
|
+
|
369
|
+
def inspect
|
370
|
+
"#<#{self.class}>"
|
371
|
+
end
|
372
|
+
|
373
|
+
def <<(str)
|
374
|
+
call_block(str, &@block) if @block
|
375
|
+
end
|
376
|
+
|
377
|
+
private
|
378
|
+
|
379
|
+
# This method is needed because @block must be called by yield,
|
380
|
+
# not Proc#call. You can see difference when using `break' in
|
381
|
+
# the block.
|
382
|
+
def call_block(str)
|
383
|
+
yield str
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
|
388
|
+
module NetPrivate #:nodoc: obsolete
|
389
|
+
Socket = ::Net::InternetMessageIO
|
390
|
+
end
|
391
|
+
|
392
|
+
end # module Net
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require './lib/rubysl/net/protocol/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "rubysl-net-protocol"
|
6
|
+
spec.version = RubySL::Net::Protocol::VERSION
|
7
|
+
spec.authors = ["Brian Shirai"]
|
8
|
+
spec.email = ["brixen@gmail.com"]
|
9
|
+
spec.description = %q{Ruby standard library net-protocol.}
|
10
|
+
spec.summary = %q{Ruby standard library net-protocol.}
|
11
|
+
spec.homepage = "https://github.com/rubysl/rubysl-net-protocol"
|
12
|
+
spec.license = "BSD"
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split($/)
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
20
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubysl-net-protocol
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Shirai
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: Ruby standard library net-protocol.
|
42
|
+
email:
|
43
|
+
- brixen@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- lib/net/protocol.rb
|
54
|
+
- lib/rubysl/net/protocol.rb
|
55
|
+
- lib/rubysl/net/protocol/protocol.rb
|
56
|
+
- lib/rubysl/net/protocol/version.rb
|
57
|
+
- rubysl-net-protocol.gemspec
|
58
|
+
homepage: https://github.com/rubysl/rubysl-net-protocol
|
59
|
+
licenses:
|
60
|
+
- BSD
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 2.0.7
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Ruby standard library net-protocol.
|
82
|
+
test_files: []
|