net-protocol 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a89e13a67cbddeb513e263e4144b6571764d29575e708fa41bde6b34f22a1861
4
+ data.tar.gz: 0ebb7c5808ba457116c5824ae27f879adc1dca00141747edeaa573e469d00391
5
+ SHA512:
6
+ metadata.gz: 561d1dae475c39c9cf2de94c3b9fcc196c134b1f5639b41cd6159d3fd4bba4faf5cd45815cbc9f4b7cf3d57a634032a9a402ff571f6f0ec9c811ca8fa8e67688
7
+ data.tar.gz: 181700c6865de4b86d2db0c52c7072e40c66dc2bbf5b3ee64747acc5e5c7c46c96d7e625ef068d8089de15a54f346a2c8566c23e1ae842e7ec5d3767f7c7d6f7
@@ -0,0 +1,24 @@
1
+ name: ubuntu
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ name: build (${{ matrix.ruby }} / ${{ matrix.os }})
8
+ strategy:
9
+ matrix:
10
+ ruby: [ 2.7, 2.6, 2.5, 2.4, head ]
11
+ os: [ ubuntu-latest, macos-latest ]
12
+ runs-on: ${{ matrix.os }}
13
+ steps:
14
+ - uses: actions/checkout@master
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby }}
19
+ - name: Install dependencies
20
+ run: |
21
+ gem install bundler --no-document
22
+ bundle install
23
+ - name: Run test
24
+ run: rake test
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ gem "test-unit"
@@ -0,0 +1,23 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ net-protocol (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ power_assert (1.1.5)
10
+ rake (12.3.3)
11
+ test-unit (3.3.5)
12
+ power_assert
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ net-protocol!
19
+ rake
20
+ test-unit
21
+
22
+ BUNDLED WITH
23
+ 2.1.4
@@ -0,0 +1,29 @@
1
+ # Net::Protocol
2
+
3
+ The abstruct interface for net-* client.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'net-protocol'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install net-protocol
20
+
21
+ ## Development
22
+
23
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
24
+
25
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
26
+
27
+ ## Contributing
28
+
29
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/net-protocol.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test/lib"
6
+ t.ruby_opts << "-rhelper"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "net/protocol"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,506 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # = net/protocol.rb
4
+ #
5
+ #--
6
+ # Copyright (c) 1999-2004 Yukihiro Matsumoto
7
+ # Copyright (c) 1999-2004 Minero Aoki
8
+ #
9
+ # written and maintained by Minero Aoki <aamine@loveruby.net>
10
+ #
11
+ # This program is free software. You can re-distribute and/or
12
+ # modify this program under the same terms as Ruby itself,
13
+ # Ruby Distribute License or GNU General Public License.
14
+ #
15
+ # $Id$
16
+ #++
17
+ #
18
+ # WARNING: This file is going to remove.
19
+ # Do not rely on the implementation written in this file.
20
+ #
21
+
22
+ require 'socket'
23
+ require 'timeout'
24
+ require 'io/wait'
25
+
26
+ module Net # :nodoc:
27
+
28
+ class Protocol #:nodoc: internal use only
29
+ private
30
+ def Protocol.protocol_param(name, val)
31
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
32
+ def #{name}
33
+ #{val}
34
+ end
35
+ End
36
+ end
37
+
38
+ def ssl_socket_connect(s, timeout)
39
+ if timeout
40
+ while true
41
+ raise Net::OpenTimeout if timeout <= 0
42
+ start = Process.clock_gettime Process::CLOCK_MONOTONIC
43
+ # to_io is required because SSLSocket doesn't have wait_readable yet
44
+ case s.connect_nonblock(exception: false)
45
+ when :wait_readable; s.to_io.wait_readable(timeout)
46
+ when :wait_writable; s.to_io.wait_writable(timeout)
47
+ else; break
48
+ end
49
+ timeout -= Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
50
+ end
51
+ else
52
+ s.connect
53
+ end
54
+ end
55
+ end
56
+
57
+
58
+ class ProtocolError < StandardError; end
59
+ class ProtoSyntaxError < ProtocolError; end
60
+ class ProtoFatalError < ProtocolError; end
61
+ class ProtoUnknownError < ProtocolError; end
62
+ class ProtoServerError < ProtocolError; end
63
+ class ProtoAuthError < ProtocolError; end
64
+ class ProtoCommandError < ProtocolError; end
65
+ class ProtoRetriableError < ProtocolError; end
66
+ ProtocRetryError = ProtoRetriableError
67
+
68
+ ##
69
+ # OpenTimeout, a subclass of Timeout::Error, is raised if a connection cannot
70
+ # be created within the open_timeout.
71
+
72
+ class OpenTimeout < Timeout::Error; end
73
+
74
+ ##
75
+ # ReadTimeout, a subclass of Timeout::Error, is raised if a chunk of the
76
+ # response cannot be read within the read_timeout.
77
+
78
+ class ReadTimeout < Timeout::Error
79
+ def initialize(io = nil)
80
+ @io = io
81
+ end
82
+ attr_reader :io
83
+
84
+ def message
85
+ msg = super
86
+ if @io
87
+ msg = "#{msg} with #{@io.inspect}"
88
+ end
89
+ msg
90
+ end
91
+ end
92
+
93
+ ##
94
+ # WriteTimeout, a subclass of Timeout::Error, is raised if a chunk of the
95
+ # response cannot be written within the write_timeout. Not raised on Windows.
96
+
97
+ class WriteTimeout < Timeout::Error
98
+ def initialize(io = nil)
99
+ @io = io
100
+ end
101
+ attr_reader :io
102
+
103
+ def message
104
+ msg = super
105
+ if @io
106
+ msg = "#{msg} with #{@io.inspect}"
107
+ end
108
+ msg
109
+ end
110
+ end
111
+
112
+
113
+ class BufferedIO #:nodoc: internal use only
114
+ def initialize(io, read_timeout: 60, write_timeout: 60, continue_timeout: nil, debug_output: nil)
115
+ @io = io
116
+ @read_timeout = read_timeout
117
+ @write_timeout = write_timeout
118
+ @continue_timeout = continue_timeout
119
+ @debug_output = debug_output
120
+ @rbuf = ''.b
121
+ end
122
+
123
+ attr_reader :io
124
+ attr_accessor :read_timeout
125
+ attr_accessor :write_timeout
126
+ attr_accessor :continue_timeout
127
+ attr_accessor :debug_output
128
+
129
+ def inspect
130
+ "#<#{self.class} io=#{@io}>"
131
+ end
132
+
133
+ def eof?
134
+ @io.eof?
135
+ end
136
+
137
+ def closed?
138
+ @io.closed?
139
+ end
140
+
141
+ def close
142
+ @io.close
143
+ end
144
+
145
+ #
146
+ # Read
147
+ #
148
+
149
+ public
150
+
151
+ def read(len, dest = ''.b, ignore_eof = false)
152
+ LOG "reading #{len} bytes..."
153
+ read_bytes = 0
154
+ begin
155
+ while read_bytes + @rbuf.size < len
156
+ s = rbuf_consume(@rbuf.size)
157
+ read_bytes += s.size
158
+ dest << s
159
+ rbuf_fill
160
+ end
161
+ s = rbuf_consume(len - read_bytes)
162
+ read_bytes += s.size
163
+ dest << s
164
+ rescue EOFError
165
+ raise unless ignore_eof
166
+ end
167
+ LOG "read #{read_bytes} bytes"
168
+ dest
169
+ end
170
+
171
+ def read_all(dest = ''.b)
172
+ LOG 'reading all...'
173
+ read_bytes = 0
174
+ begin
175
+ while true
176
+ s = rbuf_consume(@rbuf.size)
177
+ read_bytes += s.size
178
+ dest << s
179
+ rbuf_fill
180
+ end
181
+ rescue EOFError
182
+ ;
183
+ end
184
+ LOG "read #{read_bytes} bytes"
185
+ dest
186
+ end
187
+
188
+ def readuntil(terminator, ignore_eof = false)
189
+ begin
190
+ until idx = @rbuf.index(terminator)
191
+ rbuf_fill
192
+ end
193
+ return rbuf_consume(idx + terminator.size)
194
+ rescue EOFError
195
+ raise unless ignore_eof
196
+ return rbuf_consume(@rbuf.size)
197
+ end
198
+ end
199
+
200
+ def readline
201
+ readuntil("\n").chop
202
+ end
203
+
204
+ private
205
+
206
+ BUFSIZE = 1024 * 16
207
+
208
+ def rbuf_fill
209
+ tmp = @rbuf.empty? ? @rbuf : nil
210
+ case rv = @io.read_nonblock(BUFSIZE, tmp, exception: false)
211
+ when String
212
+ return if rv.equal?(tmp)
213
+ @rbuf << rv
214
+ rv.clear
215
+ return
216
+ when :wait_readable
217
+ (io = @io.to_io).wait_readable(@read_timeout) or raise Net::ReadTimeout.new(io)
218
+ # continue looping
219
+ when :wait_writable
220
+ # OpenSSL::Buffering#read_nonblock may fail with IO::WaitWritable.
221
+ # http://www.openssl.org/support/faq.html#PROG10
222
+ (io = @io.to_io).wait_writable(@read_timeout) or raise Net::ReadTimeout.new(io)
223
+ # continue looping
224
+ when nil
225
+ raise EOFError, 'end of file reached'
226
+ end while true
227
+ end
228
+
229
+ def rbuf_consume(len)
230
+ if len == @rbuf.size
231
+ s = @rbuf
232
+ @rbuf = ''.b
233
+ else
234
+ s = @rbuf.slice!(0, len)
235
+ end
236
+ @debug_output << %Q[-> #{s.dump}\n] if @debug_output
237
+ s
238
+ end
239
+
240
+ #
241
+ # Write
242
+ #
243
+
244
+ public
245
+
246
+ def write(*strs)
247
+ writing {
248
+ write0(*strs)
249
+ }
250
+ end
251
+
252
+ alias << write
253
+
254
+ def writeline(str)
255
+ writing {
256
+ write0 str + "\r\n"
257
+ }
258
+ end
259
+
260
+ private
261
+
262
+ def writing
263
+ @written_bytes = 0
264
+ @debug_output << '<- ' if @debug_output
265
+ yield
266
+ @debug_output << "\n" if @debug_output
267
+ bytes = @written_bytes
268
+ @written_bytes = nil
269
+ bytes
270
+ end
271
+
272
+ def write0(*strs)
273
+ @debug_output << strs.map(&:dump).join if @debug_output
274
+ orig_written_bytes = @written_bytes
275
+ strs.each_with_index do |str, i|
276
+ need_retry = true
277
+ case len = @io.write_nonblock(str, exception: false)
278
+ when Integer
279
+ @written_bytes += len
280
+ len -= str.bytesize
281
+ if len == 0
282
+ if strs.size == i+1
283
+ return @written_bytes - orig_written_bytes
284
+ else
285
+ need_retry = false
286
+ # next string
287
+ end
288
+ elsif len < 0
289
+ str = str.byteslice(len, -len)
290
+ else # len > 0
291
+ need_retry = false
292
+ # next string
293
+ end
294
+ # continue looping
295
+ when :wait_writable
296
+ (io = @io.to_io).wait_writable(@write_timeout) or raise Net::WriteTimeout.new(io)
297
+ # continue looping
298
+ end while need_retry
299
+ end
300
+ end
301
+
302
+ #
303
+ # Logging
304
+ #
305
+
306
+ private
307
+
308
+ def LOG_off
309
+ @save_debug_out = @debug_output
310
+ @debug_output = nil
311
+ end
312
+
313
+ def LOG_on
314
+ @debug_output = @save_debug_out
315
+ end
316
+
317
+ def LOG(msg)
318
+ return unless @debug_output
319
+ @debug_output << msg + "\n"
320
+ end
321
+ end
322
+
323
+
324
+ class InternetMessageIO < BufferedIO #:nodoc: internal use only
325
+ def initialize(*, **)
326
+ super
327
+ @wbuf = nil
328
+ end
329
+
330
+ #
331
+ # Read
332
+ #
333
+
334
+ def each_message_chunk
335
+ LOG 'reading message...'
336
+ LOG_off()
337
+ read_bytes = 0
338
+ while (line = readuntil("\r\n")) != ".\r\n"
339
+ read_bytes += line.size
340
+ yield line.delete_prefix('.')
341
+ end
342
+ LOG_on()
343
+ LOG "read message (#{read_bytes} bytes)"
344
+ end
345
+
346
+ # *library private* (cannot handle 'break')
347
+ def each_list_item
348
+ while (str = readuntil("\r\n")) != ".\r\n"
349
+ yield str.chop
350
+ end
351
+ end
352
+
353
+ def write_message_0(src)
354
+ prev = @written_bytes
355
+ each_crlf_line(src) do |line|
356
+ write0 dot_stuff(line)
357
+ end
358
+ @written_bytes - prev
359
+ end
360
+
361
+ #
362
+ # Write
363
+ #
364
+
365
+ def write_message(src)
366
+ LOG "writing message from #{src.class}"
367
+ LOG_off()
368
+ len = writing {
369
+ using_each_crlf_line {
370
+ write_message_0 src
371
+ }
372
+ }
373
+ LOG_on()
374
+ LOG "wrote #{len} bytes"
375
+ len
376
+ end
377
+
378
+ def write_message_by_block(&block)
379
+ LOG 'writing message from block'
380
+ LOG_off()
381
+ len = writing {
382
+ using_each_crlf_line {
383
+ begin
384
+ block.call(WriteAdapter.new(self, :write_message_0))
385
+ rescue LocalJumpError
386
+ # allow `break' from writer block
387
+ end
388
+ }
389
+ }
390
+ LOG_on()
391
+ LOG "wrote #{len} bytes"
392
+ len
393
+ end
394
+
395
+ private
396
+
397
+ def dot_stuff(s)
398
+ s.sub(/\A\./, '..')
399
+ end
400
+
401
+ def using_each_crlf_line
402
+ @wbuf = ''.b
403
+ yield
404
+ if not @wbuf.empty? # unterminated last line
405
+ write0 dot_stuff(@wbuf.chomp) + "\r\n"
406
+ elsif @written_bytes == 0 # empty src
407
+ write0 "\r\n"
408
+ end
409
+ write0 ".\r\n"
410
+ @wbuf = nil
411
+ end
412
+
413
+ def each_crlf_line(src)
414
+ buffer_filling(@wbuf, src) do
415
+ while line = @wbuf.slice!(/\A[^\r\n]*(?:\n|\r(?:\n|(?!\z)))/)
416
+ yield line.chomp("\n") + "\r\n"
417
+ end
418
+ end
419
+ end
420
+
421
+ def buffer_filling(buf, src)
422
+ case src
423
+ when String # for speeding up.
424
+ 0.step(src.size - 1, 1024) do |i|
425
+ buf << src[i, 1024]
426
+ yield
427
+ end
428
+ when File # for speeding up.
429
+ while s = src.read(1024)
430
+ buf << s
431
+ yield
432
+ end
433
+ else # generic reader
434
+ src.each do |str|
435
+ buf << str
436
+ yield if buf.size > 1024
437
+ end
438
+ yield unless buf.empty?
439
+ end
440
+ end
441
+ end
442
+
443
+
444
+ #
445
+ # The writer adapter class
446
+ #
447
+ class WriteAdapter
448
+ def initialize(socket, method)
449
+ @socket = socket
450
+ @method_id = method
451
+ end
452
+
453
+ def inspect
454
+ "#<#{self.class} socket=#{@socket.inspect}>"
455
+ end
456
+
457
+ def write(str)
458
+ @socket.__send__(@method_id, str)
459
+ end
460
+
461
+ alias print write
462
+
463
+ def <<(str)
464
+ write str
465
+ self
466
+ end
467
+
468
+ def puts(str = '')
469
+ write str.chomp("\n") + "\n"
470
+ end
471
+
472
+ def printf(*args)
473
+ write sprintf(*args)
474
+ end
475
+ end
476
+
477
+
478
+ class ReadAdapter #:nodoc: internal use only
479
+ def initialize(block)
480
+ @block = block
481
+ end
482
+
483
+ def inspect
484
+ "#<#{self.class}>"
485
+ end
486
+
487
+ def <<(str)
488
+ call_block(str, &@block) if @block
489
+ end
490
+
491
+ private
492
+
493
+ # This method is needed because @block must be called by yield,
494
+ # not Proc#call. You can see difference when using `break' in
495
+ # the block.
496
+ def call_block(str)
497
+ yield str
498
+ end
499
+ end
500
+
501
+
502
+ module NetPrivate #:nodoc: obsolete
503
+ Socket = ::Net::InternetMessageIO
504
+ end
505
+
506
+ end # module Net
@@ -0,0 +1,5 @@
1
+ module Net
2
+ class Protocol
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ begin
2
+ require_relative "lib/net/protocol/version"
3
+ rescue LoadError # Fallback to load version file in ruby core repository
4
+ require_relative "version"
5
+ end
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "net-protocol"
9
+ spec.version = Net::Protocol::VERSION
10
+ spec.authors = ["Yukihiro Matsumoto"]
11
+ spec.email = ["matz@ruby-lang.org"]
12
+
13
+ spec.summary = %q{The abstruct interface for net-* client.}
14
+ spec.description = %q{The abstruct interface for net-* client.}
15
+ spec.homepage = "https://github.com/ruby/net-protocol"
16
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = spec.homepage
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: net-protocol
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yukihiro Matsumoto
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-04-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: The abstruct interface for net-* client.
14
+ email:
15
+ - matz@ruby-lang.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".github/workflows/test.yml"
21
+ - ".gitignore"
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - README.md
25
+ - Rakefile
26
+ - bin/console
27
+ - bin/setup
28
+ - lib/net/protocol.rb
29
+ - lib/net/protocol/version.rb
30
+ - net-protocol.gemspec
31
+ homepage: https://github.com/ruby/net-protocol
32
+ licenses: []
33
+ metadata:
34
+ homepage_uri: https://github.com/ruby/net-protocol
35
+ source_code_uri: https://github.com/ruby/net-protocol
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 2.3.0
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.2.0.pre1
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: The abstruct interface for net-* client.
55
+ test_files: []