jruby-openssl 0.9.12-java → 0.9.13-java

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: fec096b2836ecf41ff7fabe0ad5623d2baaefe61
4
- data.tar.gz: 7f38c9c23b808c4067a676031dcdf919789a2447
3
+ metadata.gz: 53cfa91375f8c240492465413cf80832989950be
4
+ data.tar.gz: 95559557d8c369fc21f72087814edc4b24f0a9db
5
5
  SHA512:
6
- metadata.gz: e947998f76eb5b88011fad21f5d4f99f89ae5f2998901af639a4d8b7f3c764163b2222928b82832ce5a22d7fdd0309b503336c7b3c3a278069ec271c0bcf27ca
7
- data.tar.gz: c6a11ed1cc98646f35f56552c89fe3143621041cbabab2a16f8858b453023430efd0e4ca1292a45b7e815a562456a165f1765263f55023e4be2dc1f1d706ac76
6
+ metadata.gz: f6ece1c6fc0caa3f4fbb395f0383fba916420d1f0fa038793b94a437afca8c743e3316f37d00a9047ffec419a9ac77f817bcbc14f3f76db4148def5b5fa89093
7
+ data.tar.gz: 7699d18401244b3ef64ceaf959b46ef21cf689ed251e1476e722831a71c1679dd622463aab74d4c16fb8624bec496e9e35f6b28d6ac0baaad985789b9ccbf849
data/Rakefile CHANGED
@@ -37,8 +37,9 @@ file('lib/jopenssl.jar') { Rake::Task['jar'].invoke }
37
37
 
38
38
  require 'rake/testtask'
39
39
  Rake::TestTask.new do |task|
40
- task.libs << 'lib'
41
- task.test_files = FileList['src/test/ruby/**/test*.rb']
40
+ task.libs << 'src/test/ruby'
41
+ test_files = FileList['src/test/ruby/**/test*.rb'].to_a
42
+ task.test_files = test_files.map { |path| path.sub('src/test/ruby/', '') }
42
43
  task.verbose = true
43
44
  task.loader = :direct
44
45
  end
@@ -58,6 +59,8 @@ namespace :integration do
58
59
  end
59
60
  loader = "ARGV.each { |f| require f }"
60
61
  test_files = FileList['src/test/integration/*_test.rb'].to_a
61
- ruby "-Ilib -e \"#{loader}\" #{test_files.map { |f| "\"#{f}\"" }.join(' ')}"
62
+ test_files.map! { |path| path.sub('src/test/integration/', '') }
63
+ lib = [ 'lib', 'src/test/integration' ]
64
+ ruby "-I#{lib.join(':')} -e \"#{loader}\" #{test_files.map { |f| "\"#{f}\"" }.join(' ')}"
62
65
  end
63
66
  end
data/lib/jopenssl.jar CHANGED
Binary file
data/lib/jopenssl/load.rb CHANGED
@@ -24,7 +24,9 @@ require 'jruby'
24
24
  require 'jopenssl.jar'
25
25
  org.jruby.ext.openssl.OpenSSL.load(JRuby.runtime)
26
26
 
27
- if RUBY_VERSION > '2.2'
27
+ if RUBY_VERSION > '2.3'
28
+ load 'jopenssl23/openssl.rb'
29
+ elsif RUBY_VERSION > '2.2'
28
30
  load 'jopenssl22/openssl.rb'
29
31
  elsif RUBY_VERSION > '2.1'
30
32
  load 'jopenssl21/openssl.rb'
@@ -1,6 +1,11 @@
1
1
  module Jopenssl
2
+ VERSION = '0.9.13'
3
+ BOUNCY_CASTLE_VERSION = '1.50'
4
+ # @deprecated
2
5
  module Version
3
- VERSION = '0.9.12'
4
- BOUNCY_CASTLE_VERSION = '1.50'
6
+ # @private
7
+ VERSION = Jopenssl::VERSION
8
+ # @private
9
+ BOUNCY_CASTLE_VERSION = Jopenssl::BOUNCY_CASTLE_VERSION
5
10
  end
6
- end
11
+ end
@@ -15,42 +15,154 @@
15
15
  =end
16
16
 
17
17
  require "openssl/buffering"
18
- require 'fcntl' # used by OpenSSL::SSL::Nonblock (if loaded)
18
+ require "fcntl"
19
19
 
20
20
  module OpenSSL
21
21
  module SSL
22
+ class SSLContext
23
+ DEFAULT_PARAMS = {
24
+ :ssl_version => "SSLv23",
25
+ :verify_mode => OpenSSL::SSL::VERIFY_PEER,
26
+ :ciphers => %w{
27
+ ECDHE-ECDSA-AES128-GCM-SHA256
28
+ ECDHE-RSA-AES128-GCM-SHA256
29
+ ECDHE-ECDSA-AES256-GCM-SHA384
30
+ ECDHE-RSA-AES256-GCM-SHA384
31
+ DHE-RSA-AES128-GCM-SHA256
32
+ DHE-DSS-AES128-GCM-SHA256
33
+ DHE-RSA-AES256-GCM-SHA384
34
+ DHE-DSS-AES256-GCM-SHA384
35
+ ECDHE-ECDSA-AES128-SHA256
36
+ ECDHE-RSA-AES128-SHA256
37
+ ECDHE-ECDSA-AES128-SHA
38
+ ECDHE-RSA-AES128-SHA
39
+ ECDHE-ECDSA-AES256-SHA384
40
+ ECDHE-RSA-AES256-SHA384
41
+ ECDHE-ECDSA-AES256-SHA
42
+ ECDHE-RSA-AES256-SHA
43
+ DHE-RSA-AES128-SHA256
44
+ DHE-RSA-AES256-SHA256
45
+ DHE-RSA-AES128-SHA
46
+ DHE-RSA-AES256-SHA
47
+ DHE-DSS-AES128-SHA256
48
+ DHE-DSS-AES256-SHA256
49
+ DHE-DSS-AES128-SHA
50
+ DHE-DSS-AES256-SHA
51
+ AES128-GCM-SHA256
52
+ AES256-GCM-SHA384
53
+ AES128-SHA256
54
+ AES256-SHA256
55
+ AES128-SHA
56
+ AES256-SHA
57
+ ECDHE-ECDSA-RC4-SHA
58
+ ECDHE-RSA-RC4-SHA
59
+ RC4-SHA
60
+ }.join(":"),
61
+ :options => -> {
62
+ opts = OpenSSL::SSL::OP_ALL
63
+ opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
64
+ opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
65
+ opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
66
+ opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
67
+ opts
68
+ }.call
69
+ } unless const_defined? :DEFAULT_PARAMS # JRuby does it in Java
70
+
71
+ unless const_defined? :DEFAULT_CERT_STORE # JRuby specific
72
+ DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
73
+ DEFAULT_CERT_STORE.set_default_paths
74
+ if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
75
+ DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
76
+ end
77
+ end
78
+
79
+ ##
80
+ # Sets the parameters for this SSL context to the values in +params+.
81
+ # The keys in +params+ must be assignment methods on SSLContext.
82
+ #
83
+ # If the verify_mode is not VERIFY_NONE and ca_file, ca_path and
84
+ # cert_store are not set then the system default certificate store is
85
+ # used.
86
+
87
+ def set_params(params={})
88
+ params = DEFAULT_PARAMS.merge(params)
89
+ params.each{|name, value| self.__send__("#{name}=", value) }
90
+ if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
91
+ unless self.ca_file or self.ca_path or self.cert_store
92
+ self.cert_store = DEFAULT_CERT_STORE
93
+ end
94
+ end
95
+ return params
96
+ end unless method_defined? :set_params # JRuby: hooked up in "native" Java
97
+ end
98
+
99
+ module SocketForwarder
100
+ def addr
101
+ to_io.addr
102
+ end
103
+
104
+ def peeraddr
105
+ to_io.peeraddr
106
+ end
107
+
108
+ def setsockopt(level, optname, optval)
109
+ to_io.setsockopt(level, optname, optval)
110
+ end
111
+
112
+ def getsockopt(level, optname)
113
+ to_io.getsockopt(level, optname)
114
+ end
115
+
116
+ def fcntl(*args)
117
+ to_io.fcntl(*args)
118
+ end
119
+
120
+ def closed?
121
+ to_io.closed?
122
+ end
123
+
124
+ def do_not_reverse_lookup=(flag)
125
+ to_io.do_not_reverse_lookup = flag
126
+ end
127
+ end unless const_defined? :SocketForwarder # JRuby: hooked up in "native" Java
128
+
129
+ module Nonblock
130
+ def initialize(*args)
131
+ flag = File::NONBLOCK
132
+ flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
133
+ @io.fcntl(Fcntl::F_SETFL, flag)
134
+ super
135
+ end
136
+ end unless const_defined? :Nonblock # JRuby: hooked up in "native" Java
22
137
 
23
- # FIXME: Using the old non-ASN1 logic here because our ASN1 appears to
24
- # return the wrong types for some decoded objects.
25
- # @see https://github.com/jruby/jruby/issues/1102
26
- # @private
27
138
  def verify_certificate_identity(cert, hostname)
28
139
  should_verify_common_name = true
29
140
  cert.extensions.each { |ext|
30
141
  next if ext.oid != "subjectAltName"
31
142
  ext.value.split(/,\s+/).each { |general_name|
32
- # MRI 1.9.3 (since we parse ASN.1 differently)
33
- # when 2 # dNSName in GeneralName (RFC5280)
143
+ #case san.tag
144
+ # MRI 2.2.3 (JRuby parses ASN.1 differently)
145
+ #when 2 # dNSName in GeneralName (RFC5280)
34
146
  if /\ADNS:(.*)/ =~ general_name
35
147
  should_verify_common_name = false
36
148
  return true if verify_hostname(hostname, $1)
37
- # MRI 1.9.3 (since we parse ASN.1 differently)
38
- # when 7 # iPAddress in GeneralName (RFC5280)
149
+ # MRI 2.2.3 (JRuby parses ASN.1 differently)
150
+ #when 7 # iPAddress in GeneralName (RFC5280)
39
151
  elsif /\AIP(?: Address)?:(.*)/ =~ general_name
40
152
  should_verify_common_name = false
41
153
  return true if $1 == hostname
42
- # NOTE: bellow logic makes little sense as we read exts differently
43
- #value = $1 # follows GENERAL_NAME_print() in x509v3/v3_alt.c
44
- #if value.size == 4
45
- # return true if value.unpack('C*').join('.') == hostname
46
- #elsif value.size == 16
47
- # return true if value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
154
+ # NOTE: bellow logic makes little sense JRuby reads exts differently
155
+ # follows GENERAL_NAME_print() in x509v3/v3_alt.c
156
+ #if san.value.size == 4
157
+ # return true if san.value.unpack('C*').join('.') == hostname
158
+ #elsif san.value.size == 16
159
+ # return true if san.value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
48
160
  #end
49
161
  end
50
162
  }
51
163
  }
52
164
  if should_verify_common_name
53
- cert.subject.to_a.each { |oid, value|
165
+ cert.subject.to_a.each{|oid, value|
54
166
  if oid == "CN"
55
167
  return true if verify_hostname(hostname, value)
56
168
  end
@@ -122,12 +234,33 @@ module OpenSSL
122
234
  # This method MUST be called after calling #connect to ensure that the
123
235
  # hostname of a remote peer has been verified.
124
236
  def post_connection_check(hostname)
237
+ if peer_cert.nil?
238
+ msg = "Peer verification enabled, but no certificate received."
239
+ if using_anon_cipher?
240
+ msg += " Anonymous cipher suite #{cipher[0]} was negotiated. Anonymous suites must be disabled to use peer verification."
241
+ end
242
+ raise SSLError, msg
243
+ end
244
+
125
245
  unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
126
246
  raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
127
247
  end
128
248
  return true
129
249
  end
130
250
 
251
+ #def session
252
+ # SSL::Session.new(self)
253
+ #rescue SSL::Session::SessionError
254
+ # nil
255
+ #end
256
+
257
+ private
258
+
259
+ def using_anon_cipher?
260
+ ctx = OpenSSL::SSL::SSLContext.new
261
+ ctx.ciphers = "aNULL"
262
+ ctx.ciphers.include?(cipher)
263
+ end
131
264
  end
132
265
 
133
266
  ##
@@ -178,8 +311,12 @@ module OpenSSL
178
311
  ssl.sync_close = true
179
312
  ssl.accept if @start_immediately
180
313
  ssl
181
- rescue SSLError => ex
182
- sock.close
314
+ rescue Exception => ex
315
+ if ssl
316
+ ssl.close
317
+ else
318
+ sock.close
319
+ end
183
320
  raise ex
184
321
  end
185
322
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: false
2
+ =begin
3
+ = Info
4
+ 'OpenSSL for Ruby 2' project
5
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
6
+ All rights reserved.
7
+
8
+ = Licence
9
+ This program is licensed under the same licence as Ruby.
10
+ (See the file 'LICENCE'.)
11
+ =end
12
+
13
+ require 'openssl/bn'
14
+ require 'openssl/pkey'
15
+ require 'openssl/cipher'
16
+ require 'openssl/config'
17
+ require 'openssl/digest'
18
+ require 'openssl/x509'
19
+ require 'openssl/ssl'
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: false
2
+ #--
3
+ #
4
+ # = Ruby-space definitions that completes C-space funcs for BN
5
+ #
6
+ # = Info
7
+ # 'OpenSSL for Ruby 2' project
8
+ # Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
9
+ # All rights reserved.
10
+ #
11
+ # = Licence
12
+ # This program is licensed under the same licence as Ruby.
13
+ # (See the file 'LICENCE'.)
14
+ #++
15
+
16
+ module OpenSSL
17
+ class BN
18
+ def pretty_print(q)
19
+ q.object_group(self) {
20
+ q.text ' '
21
+ q.text to_i.to_s
22
+ }
23
+ end
24
+ end # BN
25
+ end # OpenSSL
26
+
27
+ ##
28
+ # Add double dispatch to Integer
29
+ #
30
+ class Integer
31
+ # Casts an Integer as an OpenSSL::BN
32
+ #
33
+ # See `man bn` for more info.
34
+ def to_bn
35
+ OpenSSL::BN::new(self)
36
+ end
37
+ end # Integer
@@ -0,0 +1,453 @@
1
+ # coding: binary
2
+ # frozen_string_literal: false
3
+ #--
4
+ #= Info
5
+ # 'OpenSSL for Ruby 2' project
6
+ # Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
7
+ # All rights reserved.
8
+ #
9
+ #= Licence
10
+ # This program is licensed under the same licence as Ruby.
11
+ # (See the file 'LICENCE'.)
12
+ #++
13
+
14
+ ##
15
+ # OpenSSL IO buffering mix-in module.
16
+ #
17
+ # This module allows an OpenSSL::SSL::SSLSocket to behave like an IO.
18
+ #
19
+ # You typically won't use this module directly, you can see it implemented in
20
+ # OpenSSL::SSL::SSLSocket.
21
+
22
+ module OpenSSL::Buffering
23
+ include Enumerable
24
+
25
+ ##
26
+ # The "sync mode" of the SSLSocket.
27
+ #
28
+ # See IO#sync for full details.
29
+
30
+ attr_accessor :sync
31
+
32
+ ##
33
+ # Default size to read from or write to the SSLSocket for buffer operations.
34
+
35
+ BLOCK_SIZE = 1024*16
36
+
37
+ ##
38
+ # Creates an instance of OpenSSL's buffering IO module.
39
+
40
+ def initialize(*)
41
+ # super
42
+ @eof = false
43
+ @rbuffer = ""
44
+ @sync = @io.sync
45
+ end
46
+
47
+ #
48
+ # for reading.
49
+ #
50
+ private
51
+
52
+ ##
53
+ # Fills the buffer from the underlying SSLSocket
54
+
55
+ def fill_rbuff
56
+ begin
57
+ @rbuffer << self.sysread(BLOCK_SIZE)
58
+ rescue Errno::EAGAIN
59
+ retry
60
+ rescue EOFError
61
+ @eof = true
62
+ end
63
+ end
64
+
65
+ ##
66
+ # Consumes +size+ bytes from the buffer
67
+
68
+ def consume_rbuff(size=nil)
69
+ if @rbuffer.empty?
70
+ nil
71
+ else
72
+ size = @rbuffer.size unless size
73
+ ret = @rbuffer[0, size]
74
+ @rbuffer[0, size] = ""
75
+ ret
76
+ end
77
+ end
78
+
79
+ public
80
+
81
+ ##
82
+ # Reads +size+ bytes from the stream. If +buf+ is provided it must
83
+ # reference a string which will receive the data.
84
+ #
85
+ # See IO#read for full details.
86
+
87
+ def read(size=nil, buf=nil)
88
+ if size == 0
89
+ if buf
90
+ buf.clear
91
+ return buf
92
+ else
93
+ return ""
94
+ end
95
+ end
96
+ until @eof
97
+ break if size && size <= @rbuffer.size
98
+ fill_rbuff
99
+ end
100
+ ret = consume_rbuff(size) || ""
101
+ if buf
102
+ buf.replace(ret)
103
+ ret = buf
104
+ end
105
+ (size && ret.empty?) ? nil : ret
106
+ end
107
+
108
+ ##
109
+ # Reads at most +maxlen+ bytes from the stream. If +buf+ is provided it
110
+ # must reference a string which will receive the data.
111
+ #
112
+ # See IO#readpartial for full details.
113
+
114
+ def readpartial(maxlen, buf=nil)
115
+ if maxlen == 0
116
+ if buf
117
+ buf.clear
118
+ return buf
119
+ else
120
+ return ""
121
+ end
122
+ end
123
+ if @rbuffer.empty?
124
+ begin
125
+ return sysread(maxlen, buf)
126
+ rescue Errno::EAGAIN
127
+ retry
128
+ end
129
+ end
130
+ ret = consume_rbuff(maxlen)
131
+ if buf
132
+ buf.replace(ret)
133
+ ret = buf
134
+ end
135
+ raise EOFError if ret.empty?
136
+ ret
137
+ end
138
+
139
+ ##
140
+ # Reads at most +maxlen+ bytes in the non-blocking manner.
141
+ #
142
+ # When no data can be read without blocking it raises
143
+ # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
144
+ #
145
+ # IO::WaitReadable means SSL needs to read internally so read_nonblock
146
+ # should be called again when the underlying IO is readable.
147
+ #
148
+ # IO::WaitWritable means SSL needs to write internally so read_nonblock
149
+ # should be called again after the underlying IO is writable.
150
+ #
151
+ # OpenSSL::Buffering#read_nonblock needs two rescue clause as follows:
152
+ #
153
+ # # emulates blocking read (readpartial).
154
+ # begin
155
+ # result = ssl.read_nonblock(maxlen)
156
+ # rescue IO::WaitReadable
157
+ # IO.select([io])
158
+ # retry
159
+ # rescue IO::WaitWritable
160
+ # IO.select(nil, [io])
161
+ # retry
162
+ # end
163
+ #
164
+ # Note that one reason that read_nonblock writes to the underlying IO is
165
+ # when the peer requests a new TLS/SSL handshake. See openssl the FAQ for
166
+ # more details. http://www.openssl.org/support/faq.html
167
+
168
+ def read_nonblock(maxlen, buf=nil, exception: true)
169
+ if maxlen == 0
170
+ if buf
171
+ buf.clear
172
+ return buf
173
+ else
174
+ return ""
175
+ end
176
+ end
177
+ if @rbuffer.empty?
178
+ return sysread_nonblock(maxlen, buf, exception: exception)
179
+ end
180
+ ret = consume_rbuff(maxlen)
181
+ if buf
182
+ buf.replace(ret)
183
+ ret = buf
184
+ end
185
+ raise EOFError if ret.empty?
186
+ ret
187
+ end
188
+
189
+ ##
190
+ # Reads the next "line+ from the stream. Lines are separated by +eol+. If
191
+ # +limit+ is provided the result will not be longer than the given number of
192
+ # bytes.
193
+ #
194
+ # +eol+ may be a String or Regexp.
195
+ #
196
+ # Unlike IO#gets the line read will not be assigned to +$_+.
197
+ #
198
+ # Unlike IO#gets the separator must be provided if a limit is provided.
199
+
200
+ def gets(eol=$/, limit=nil)
201
+ idx = @rbuffer.index(eol)
202
+ until @eof
203
+ break if idx
204
+ fill_rbuff
205
+ idx = @rbuffer.index(eol)
206
+ end
207
+ if eol.is_a?(Regexp)
208
+ size = idx ? idx+$&.size : nil
209
+ else
210
+ size = idx ? idx+eol.size : nil
211
+ end
212
+ if size && limit && limit >= 0
213
+ size = [size, limit].min
214
+ end
215
+ consume_rbuff(size)
216
+ end
217
+
218
+ ##
219
+ # Executes the block for every line in the stream where lines are separated
220
+ # by +eol+.
221
+ #
222
+ # See also #gets
223
+
224
+ def each(eol=$/)
225
+ while line = self.gets(eol)
226
+ yield line
227
+ end
228
+ end
229
+ alias each_line each
230
+
231
+ ##
232
+ # Reads lines from the stream which are separated by +eol+.
233
+ #
234
+ # See also #gets
235
+
236
+ def readlines(eol=$/)
237
+ ary = []
238
+ while line = self.gets(eol)
239
+ ary << line
240
+ end
241
+ ary
242
+ end
243
+
244
+ ##
245
+ # Reads a line from the stream which is separated by +eol+.
246
+ #
247
+ # Raises EOFError if at end of file.
248
+
249
+ def readline(eol=$/)
250
+ raise EOFError if eof?
251
+ gets(eol)
252
+ end
253
+
254
+ ##
255
+ # Reads one character from the stream. Returns nil if called at end of
256
+ # file.
257
+
258
+ def getc
259
+ read(1)
260
+ end
261
+
262
+ ##
263
+ # Calls the given block once for each byte in the stream.
264
+
265
+ def each_byte # :yields: byte
266
+ while c = getc
267
+ yield(c.ord)
268
+ end
269
+ end
270
+
271
+ ##
272
+ # Reads a one-character string from the stream. Raises an EOFError at end
273
+ # of file.
274
+
275
+ def readchar
276
+ raise EOFError if eof?
277
+ getc
278
+ end
279
+
280
+ ##
281
+ # Pushes character +c+ back onto the stream such that a subsequent buffered
282
+ # character read will return it.
283
+ #
284
+ # Unlike IO#getc multiple bytes may be pushed back onto the stream.
285
+ #
286
+ # Has no effect on unbuffered reads (such as #sysread).
287
+
288
+ def ungetc(c)
289
+ @rbuffer[0,0] = c.chr
290
+ end
291
+
292
+ ##
293
+ # Returns true if the stream is at file which means there is no more data to
294
+ # be read.
295
+
296
+ def eof?
297
+ fill_rbuff if !@eof && @rbuffer.empty?
298
+ @eof && @rbuffer.empty?
299
+ end
300
+ alias eof eof?
301
+
302
+ #
303
+ # for writing.
304
+ #
305
+ private
306
+
307
+ ##
308
+ # Writes +s+ to the buffer. When the buffer is full or #sync is true the
309
+ # buffer is flushed to the underlying socket.
310
+
311
+ def do_write(s)
312
+ @wbuffer = "" unless defined? @wbuffer
313
+ @wbuffer << s
314
+ @wbuffer.force_encoding(Encoding::BINARY)
315
+ @sync ||= false
316
+ if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
317
+ remain = idx ? idx + $/.size : @wbuffer.length
318
+ nwritten = 0
319
+ while remain > 0
320
+ str = @wbuffer[nwritten,remain]
321
+ begin
322
+ nwrote = syswrite(str)
323
+ rescue Errno::EAGAIN
324
+ retry
325
+ end
326
+ remain -= nwrote
327
+ nwritten += nwrote
328
+ end
329
+ @wbuffer[0,nwritten] = ""
330
+ end
331
+ end
332
+
333
+ public
334
+
335
+ ##
336
+ # Writes +s+ to the stream. If the argument is not a string it will be
337
+ # converted using String#to_s. Returns the number of bytes written.
338
+
339
+ def write(s)
340
+ do_write(s)
341
+ s.bytesize
342
+ end
343
+
344
+ ##
345
+ # Writes +str+ in the non-blocking manner.
346
+ #
347
+ # If there is buffered data, it is flushed first. This may block.
348
+ #
349
+ # write_nonblock returns number of bytes written to the SSL connection.
350
+ #
351
+ # When no data can be written without blocking it raises
352
+ # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
353
+ #
354
+ # IO::WaitReadable means SSL needs to read internally so write_nonblock
355
+ # should be called again after the underlying IO is readable.
356
+ #
357
+ # IO::WaitWritable means SSL needs to write internally so write_nonblock
358
+ # should be called again after underlying IO is writable.
359
+ #
360
+ # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows.
361
+ #
362
+ # # emulates blocking write.
363
+ # begin
364
+ # result = ssl.write_nonblock(str)
365
+ # rescue IO::WaitReadable
366
+ # IO.select([io])
367
+ # retry
368
+ # rescue IO::WaitWritable
369
+ # IO.select(nil, [io])
370
+ # retry
371
+ # end
372
+ #
373
+ # Note that one reason that write_nonblock reads from the underlying IO
374
+ # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ
375
+ # for more details. http://www.openssl.org/support/faq.html
376
+
377
+ def write_nonblock(s, exception: true)
378
+ flush
379
+ syswrite_nonblock(s, exception: exception)
380
+ end
381
+
382
+ ##
383
+ # Writes +s+ to the stream. +s+ will be converted to a String using
384
+ # String#to_s.
385
+
386
+ def << (s)
387
+ do_write(s)
388
+ self
389
+ end
390
+
391
+ ##
392
+ # Writes +args+ to the stream along with a record separator.
393
+ #
394
+ # See IO#puts for full details.
395
+
396
+ def puts(*args)
397
+ s = ""
398
+ if args.empty?
399
+ s << "\n"
400
+ end
401
+ args.each{|arg|
402
+ s << arg.to_s
403
+ if $/ && /\n\z/ !~ s
404
+ s << "\n"
405
+ end
406
+ }
407
+ do_write(s)
408
+ nil
409
+ end
410
+
411
+ ##
412
+ # Writes +args+ to the stream.
413
+ #
414
+ # See IO#print for full details.
415
+
416
+ def print(*args)
417
+ s = ""
418
+ args.each{ |arg| s << arg.to_s }
419
+ do_write(s)
420
+ nil
421
+ end
422
+
423
+ ##
424
+ # Formats and writes to the stream converting parameters under control of
425
+ # the format string.
426
+ #
427
+ # See Kernel#sprintf for format string details.
428
+
429
+ def printf(s, *args)
430
+ do_write(s % args)
431
+ nil
432
+ end
433
+
434
+ ##
435
+ # Flushes buffered data to the SSLSocket.
436
+
437
+ def flush
438
+ osync = @sync
439
+ @sync = true
440
+ do_write ""
441
+ return self
442
+ ensure
443
+ @sync = osync
444
+ end
445
+
446
+ ##
447
+ # Closes the SSLSocket and flushes any unwritten data.
448
+
449
+ def close
450
+ flush rescue nil
451
+ sysclose
452
+ end
453
+ end