h2 0.3.1 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dfd3251c0bd00b269688a2e87b54e009be339aff
4
- data.tar.gz: ec1799dd72604f8e089bd7be923f1f5083ec8c2d
3
+ metadata.gz: 59101b19f83a2994cc9186c11121c95645e5cdf4
4
+ data.tar.gz: fd22e1173757e89c855641daf391e9b55de79204
5
5
  SHA512:
6
- metadata.gz: e99a4e6d24b280b3ca9b60189e067c4382f585723a8aae28185e5e85423d0f2ad11cb5d8758082bc323f51a9fcffbdbaa522c12552d1777d27c37c93994ddb62
7
- data.tar.gz: cb8952f4b441870ee7b8fc3d1dd839c74fd653ce8a7b41eaf1d0c4b0a84fb4eab687c995f2505b1fe3ccaa5fb6134f8739ba8fbad8fbd419f838ef9e0c0ca16b
6
+ metadata.gz: 3431f613af4aea436ae44e2ef3e617408012553bf9d3b5ab36b6d4d0068d46d7485560b02037cb98b6eac7edaa8d07f3b79350e150c57330c4fe8f66c2d8a4be
7
+ data.tar.gz: f8e98e3d6838005d1c83848a35f48166eeb76a06dc87b53b9cf03c7ea6543c7b339285626a9d8de9a4ce90e2d1859babd3b78cd4e2d51f0088541e91f84dcee1
data/.travis.yml CHANGED
@@ -1,9 +1,10 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.3.0
5
- - 2.3.1
6
- - 2.3.2
7
- - 2.3.3
8
- - 2.4.0
4
+ - 2.2.7
5
+ - 2.3.4
9
6
  - 2.4.1
7
+ - jruby-9.1.12.0
8
+ matrix:
9
+ allow_failures:
10
+ - rvm: jruby-9.1.12.0
data/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
1
  h2 changelog
2
2
  ============
3
3
 
4
+ ### 0.4.0 17 jun 2017
5
+
6
+ * downgrade required ruby version to 2.2
7
+ * update .travis.yml for latest supported versions
8
+ * refactor exceptionless IO handling to prepended modules
9
+ * refactor On#on for lack of safe-nil operator
10
+ * refactor SSL context handling for 2.2/jruby
11
+
4
12
  ### 0.3.1 13 may 2017
5
13
 
6
14
  * `servername` should not be set on client socket when IP address (#1)
data/Gemfile CHANGED
@@ -12,6 +12,7 @@ end
12
12
 
13
13
  group :development, :test do
14
14
  gem 'awesome_print'
15
- gem 'pry-byebug'
16
- gem 'reel', require: 'reel/h2', git: 'https://github.com/kenichi/reel', branch: 'h2'
15
+ gem 'guard-rake'
16
+ gem 'pry-byebug', platforms: [:mri]
17
+ gem 'reel', require: 'reel/h2', git: 'https://github.com/kenichi/reel', branch: 'rebase_h2'
17
18
  end
data/Guardfile ADDED
@@ -0,0 +1,3 @@
1
+ guard :rake, task: 'test' do
2
+ watch %r{^(lib|test).*}
3
+ end
data/bin/console CHANGED
@@ -4,22 +4,5 @@ require 'bundler/setup'
4
4
  require 'h2'
5
5
  require 'irb'
6
6
 
7
- #Bundler.require :development
8
-
9
- def trunc_payload f
10
- x = f.dup
11
- size = x[:payload]&.to_s&.bytesize || 0
12
- x[:payload] = "#{size} redacted" if size > 64
13
- x
14
- end
15
-
16
- def new_client
17
- # H2::Client.new url: 'https://127.0.0.1:4430', tls: { ca_file: '/Users/ken/src/ruby/other_reel/tmp/certs/ca.crt' } do |client|
18
- # H2::Client.new url: 'http://127.0.0.1:1234' do |client|
19
- H2::Client.new url: 'https://vux.nakamura.io:4430', tls: { ca_file: '/usr/local/etc/cacert-201611290415.pem' } do |client|
20
- client.client.on(:frame_sent){|f| STDERR.puts ">> #{trunc_payload(f).inspect}"}
21
- client.client.on(:frame_received){|f| STDERR.puts "<< #{trunc_payload(f).inspect}"}
22
- end
23
- end
24
-
7
+ Bundler.require :development
25
8
  IRB.start
data/exe/h2 CHANGED
@@ -66,6 +66,10 @@ OptionParser.new do |o|
66
66
  options[:method] = meth
67
67
  end
68
68
 
69
+ o.on '--version', 'print version information' do
70
+ puts "#{H2::USER_AGENT['user-agent']} using http-2-#{HTTP2::VERSION}"
71
+ exit
72
+ end
69
73
 
70
74
  end.parse!
71
75
 
data/h2.gemspec CHANGED
@@ -1,15 +1,13 @@
1
1
  # coding: utf-8
2
2
  require_relative './lib/h2/version'
3
3
 
4
- IGNORE = %w[ test/ spec/ features/ .gitignore .travis.yml ]
5
-
6
4
  Gem::Specification.new do |spec|
7
5
  spec.name = "h2"
8
6
  spec.version = H2::VERSION
9
7
  spec.authors = ["Kenichi Nakamura"]
10
8
  spec.email = ["kenichi.nakamura@gmail.com"]
11
9
  spec.summary = 'an http/2 client based on http-2 and modern ruby'
12
- spec.description = 'a pure ruby http/2 client based on http-2 for ruby 2.3 and above'
10
+ spec.description = 'a pure ruby http/2 client based on http-2 for ruby 2.2 and above'
13
11
  spec.homepage = 'https://github.com/kenichi/h2'
14
12
  spec.license = 'MIT'
15
13
  spec.bindir = 'exe'
@@ -17,12 +15,12 @@ Gem::Specification.new do |spec|
17
15
  spec.require_paths = ['lib']
18
16
  spec.files = `git ls-files`.split.reject {|f| f.start_with? 'test', 'spec', 'features'}
19
17
 
20
- spec.required_ruby_version = '>= 2.3'
18
+ spec.required_ruby_version = '>= 2.2'
21
19
 
22
20
  spec.add_dependency 'http-2', '~> 0.8', '>= 0.8.4'
23
21
  spec.add_dependency 'colored', '1.2'
24
22
 
25
- spec.add_development_dependency "bundler", "~> 1.13"
23
+ spec.add_development_dependency "bundler", "~> 1.15"
26
24
  spec.add_development_dependency "rake", "~> 10.0"
27
25
  spec.add_development_dependency "minitest", "~> 5.0"
28
26
  end
@@ -7,13 +7,11 @@ module H2
7
7
  DEFAULT_TIMEOUT = 10
8
8
  # ON_LINUX = !!(RUBY_PLATFORM =~ /linux/)
9
9
 
10
- attr_reader :selector
11
-
12
10
  def initialize addr, port, timeout = DEFAULT_TIMEOUT
13
11
 
14
12
  # resolve name & pack addr
15
13
  family, addr = Socket.getaddrinfo(addr, port, nil, :STREAM, nil, AI_ALL).first.values_at(0,3)
16
- sockaddr = Socket.sockaddr_in port, addr
14
+ @_sockaddr = Socket.sockaddr_in port, addr
17
15
 
18
16
  super family, SOCK_STREAM
19
17
 
@@ -23,23 +21,46 @@ module H2
23
21
  # cork on linux
24
22
  # setsockopt IPPROTO_TCP, TCP_CORK, 1 if ON_LINUX
25
23
 
26
- if connect_nonblock(sockaddr, exception: false) == :wait_writable
27
- if IO.select nil, [self], nil, timeout
28
- begin
29
- connect_nonblock sockaddr
30
- rescue Errno::EISCONN
31
- rescue
32
- close
33
- raise
34
- end
35
- else
24
+ handle_wait_writable(timeout){ _connect } if _connect == :wait_writable
25
+ end
26
+
27
+ def selector
28
+ @selector ||= [self]
29
+ end
30
+
31
+ private
32
+
33
+ def _connect
34
+ connect_nonblock @_sockaddr
35
+ rescue IO::WaitWritable
36
+ :wait_writable
37
+ end
38
+
39
+ def handle_wait_writable timeout, &block
40
+ if IO.select nil, selector, nil, timeout
41
+ begin
42
+ handle_wait_writable(timeout, &block) if yield == :wait_writable
43
+ rescue Errno::EISCONN
44
+ rescue
36
45
  close
37
- raise Errno::ETIMEDOUT
46
+ raise
38
47
  end
48
+ else
49
+ close
50
+ raise Errno::ETIMEDOUT
51
+ end
52
+ end
53
+
54
+ module ExceptionlessIO
55
+
56
+ def _connect
57
+ connect_nonblock(@_sockaddr, exception: false)
39
58
  end
40
59
 
41
60
  end
42
61
 
62
+ prepend ExceptionlessIO if H2.exceptionless_io?
63
+
43
64
  end
44
65
  end
45
66
  end
data/lib/h2/client.rb CHANGED
@@ -14,7 +14,6 @@ module H2
14
14
  :promise
15
15
  ]
16
16
 
17
- ALPN_OPENSSL_MIN_VERSION = 0x10002001
18
17
  ALPN_PROTOCOLS = ['h2']
19
18
  DEFAULT_MAXLEN = 4096
20
19
  RE_IP_ADDR = Regexp.union Resolv::IPv4::Regex, Resolv::IPv6::Regex
@@ -131,6 +130,10 @@ module H2
131
130
 
132
131
  # ---
133
132
 
133
+ def selector
134
+ @selector ||= [@socket]
135
+ end
136
+
134
137
  def read maxlen = DEFAULT_MAXLEN
135
138
  main = Thread.current
136
139
  @reader = Thread.new do
@@ -145,10 +148,9 @@ module H2
145
148
  def _read maxlen = DEFAULT_MAXLEN
146
149
  begin
147
150
  data = nil
148
- selector = [@socket]
149
151
 
150
152
  loop do
151
- data = @socket.read_nonblock maxlen, exception: false
153
+ data = read_from_socket maxlen
152
154
  case data
153
155
  when :wait_readable
154
156
  IO.select selector
@@ -171,6 +173,12 @@ module H2
171
173
  end
172
174
  end
173
175
 
176
+ def read_from_socket maxlen
177
+ @socket.read_nonblock maxlen
178
+ rescue IO::WaitReadable
179
+ :wait_readable
180
+ end
181
+
174
182
  # ---
175
183
 
176
184
  def on_close
@@ -184,7 +192,7 @@ module H2
184
192
  if ::H2::Client::TCPSocket === @socket
185
193
  total = bytes.bytesize
186
194
  loop do
187
- n = @socket.sendmsg_nonblock bytes, exception: false
195
+ n = write_to_socket bytes
188
196
  if n == :wait_writable
189
197
  IO.select nil, @socket.selector
190
198
  elsif n < total
@@ -199,6 +207,12 @@ module H2
199
207
  @socket.flush
200
208
  end
201
209
 
210
+ def write_to_socket bytes
211
+ @socket.write_nonblock bytes
212
+ rescue IO::WaitWritable
213
+ :wait_writable
214
+ end
215
+
202
216
  def on_goaway *args
203
217
  on :goaway, *args
204
218
  close
@@ -240,11 +254,14 @@ module H2
240
254
  ctx.ssl_version = :TLSv1_2
241
255
  ctx.verify_mode = @tls[:verify_mode] || ( OpenSSL::SSL::VERIFY_PEER |
242
256
  OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT )
243
- set_ssl_context_protocols ctx
257
+
258
+ # https://github.com/jruby/jruby-openssl/issues/99
259
+ set_ssl_context_protocols ctx unless H2.jruby?
260
+
244
261
  ctx
245
262
  end
246
263
 
247
- if OpenSSL::OPENSSL_VERSION_NUMBER >= ALPN_OPENSSL_MIN_VERSION
264
+ if H2.alpn?
248
265
  def set_ssl_context_protocols ctx
249
266
  ctx.alpn_protocols = ALPN_PROTOCOLS
250
267
  end
@@ -254,5 +271,21 @@ module H2
254
271
  end
255
272
  end
256
273
 
274
+ # ---
275
+
276
+ module ExceptionlessIO
277
+
278
+ def read_from_socket maxlen
279
+ @socket.read_nonblock maxlen, exception: false
280
+ end
281
+
282
+ def write_to_socket bytes
283
+ @socket.write_nonblock bytes, exception: false
284
+ end
285
+
286
+ end
287
+
288
+ prepend ExceptionlessIO if H2.exceptionless_io?
289
+
257
290
  end
258
291
  end
data/lib/h2/version.rb CHANGED
@@ -1,3 +1,23 @@
1
1
  module H2
2
- VERSION = '0.3.1'
2
+ VERSION = '0.4.0'
3
+
4
+ class << self
5
+
6
+ ALPN_OPENSSL_MIN_VERSION = 0x10002001
7
+
8
+ def alpn?
9
+ exceptionless_io? && OpenSSL::OPENSSL_VERSION_NUMBER >= ALPN_OPENSSL_MIN_VERSION
10
+ end
11
+
12
+ def exceptionless_io?
13
+ RUBY_VERSION >= '2.3' && !jruby?
14
+ end
15
+
16
+ def jruby?
17
+ return @jruby if defined? @jruby
18
+ @jruby = RUBY_ENGINE == 'jruby'
19
+ end
20
+
21
+ end
22
+
3
23
  end
data/lib/h2.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'http/2'
4
4
  require 'uri'
5
-
6
5
  require 'h2/version'
7
6
 
8
7
  module H2
@@ -87,9 +86,14 @@ module H2
87
86
 
88
87
  def on event, *args, &block
89
88
  @on ||= {}
90
- return @on[event]&.call(*args) unless block_given?
91
- return @on[event] = block if block_given?
92
- self
89
+ event_handler = @on[event]
90
+ if block_given?
91
+ @on[event] = block
92
+ self
93
+ else
94
+ return if event_handler.nil?
95
+ return event_handler.call(*args)
96
+ end
93
97
  end
94
98
 
95
99
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: h2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenichi Nakamura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-13 00:00:00.000000000 Z
11
+ date: 2017-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.13'
53
+ version: '1.15'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '1.13'
60
+ version: '1.15'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rake
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -86,7 +86,7 @@ dependencies:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: '5.0'
89
- description: a pure ruby http/2 client based on http-2 for ruby 2.3 and above
89
+ description: a pure ruby http/2 client based on http-2 for ruby 2.2 and above
90
90
  email:
91
91
  - kenichi.nakamura@gmail.com
92
92
  executables:
@@ -99,6 +99,7 @@ files:
99
99
  - CHANGELOG.md
100
100
  - CODE_OF_CONDUCT.md
101
101
  - Gemfile
102
+ - Guardfile
102
103
  - LICENSE.txt
103
104
  - README.md
104
105
  - Rakefile
@@ -124,7 +125,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
125
  requirements:
125
126
  - - ">="
126
127
  - !ruby/object:Gem::Version
127
- version: '2.3'
128
+ version: '2.2'
128
129
  required_rubygems_version: !ruby/object:Gem::Requirement
129
130
  requirements:
130
131
  - - ">="