зеркало из https://github.com/github/ruby.git
* ext/openssl/ossl_ssl.c (ossl_start_ssl): should wait for that
the underlying IO become readable or writable if the error was SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. [ruby-dev:25795] * ext/openssl/ossl_ssl.c (ossl_ssl_read, ossl_ssl_write): ditto. * ext/openssl/lib/openssl/buffering.rb (Buffering#consume_rbuf): pointless eof flag resetting is deleted. (Buffering#read): should return an empty string if the specified size is zero. (Buffering#readpartial): new method. (Buffering#readline): fix typo. (Buffering#getc): return the first character of string correctly. (Buffering#readchar): fix typo. (Buffering#eof?): should read again it the input buffer is empty. (Buffering#do_write): should rescue Errno::EAGAIN. (Buffering#puts): use "\n" as the output field separator. * ext/openssl/extconf.rb: get rid of GNUmakefile generation. * text/openssl/test_pair.rb: test for IO like methods. * test/ruby/ut_eof.rb: test about empty file. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8081 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
4b0f7cecc4
Коммит
a9fb0817a1
26
ChangeLog
26
ChangeLog
|
@ -1,3 +1,29 @@
|
||||||
|
Sun Mar 6 06:34:31 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||||
|
|
||||||
|
* ext/openssl/ossl_ssl.c (ossl_start_ssl): should wait for that
|
||||||
|
the underlying IO become readable or writable if the error was
|
||||||
|
SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. [ruby-dev:25795]
|
||||||
|
|
||||||
|
* ext/openssl/ossl_ssl.c (ossl_ssl_read, ossl_ssl_write): ditto.
|
||||||
|
|
||||||
|
* ext/openssl/lib/openssl/buffering.rb
|
||||||
|
(Buffering#consume_rbuf): pointless eof flag resetting is deleted.
|
||||||
|
(Buffering#read): should return an empty string if the specified
|
||||||
|
size is zero.
|
||||||
|
(Buffering#readpartial): new method.
|
||||||
|
(Buffering#readline): fix typo.
|
||||||
|
(Buffering#getc): return the first character of string correctly.
|
||||||
|
(Buffering#readchar): fix typo.
|
||||||
|
(Buffering#eof?): should read again it the input buffer is empty.
|
||||||
|
(Buffering#do_write): should rescue Errno::EAGAIN.
|
||||||
|
(Buffering#puts): use "\n" as the output field separator.
|
||||||
|
|
||||||
|
* ext/openssl/extconf.rb: get rid of GNUmakefile generation.
|
||||||
|
|
||||||
|
* text/openssl/test_pair.rb: test for IO like methods.
|
||||||
|
|
||||||
|
* test/ruby/ut_eof.rb: test about empty file.
|
||||||
|
|
||||||
Sat Mar 5 17:48:31 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
|
Sat Mar 5 17:48:31 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
|
||||||
|
|
||||||
* dir.c (rb_glob): fixed mismatch of argument.
|
* dir.c (rb_glob): fixed mismatch of argument.
|
||||||
|
|
|
@ -113,33 +113,5 @@ have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h")
|
||||||
have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
|
have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
|
||||||
|
|
||||||
message "=== Checking done. ===\n"
|
message "=== Checking done. ===\n"
|
||||||
$distcleanfiles << "GNUmakefile" << "dep"
|
|
||||||
create_makefile("openssl")
|
create_makefile("openssl")
|
||||||
if /gcc/ =~ CONFIG["CC"]
|
|
||||||
File.open("GNUmakefile", "w") {|f|
|
|
||||||
f.print <<EOD
|
|
||||||
include Makefile
|
|
||||||
|
|
||||||
SRCS = $(OBJS:.o=.c)
|
|
||||||
|
|
||||||
test-link: $(OBJS)
|
|
||||||
$(CC) $(DLDFLAGS) #{OUTFLAG}.testlink $(OBJS) $(LIBPATH) $(LIBS) $(LOCAL_LIBS)
|
|
||||||
@$(RM) .testlink
|
|
||||||
@echo "Done."
|
|
||||||
|
|
||||||
dep:
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(SRCS) -MM | \\
|
|
||||||
$(RUBY) -p -e 'BEGIN{S = []' \\
|
|
||||||
-e 'while !ARGV.empty? and /^(\\w+)=(.*)/ =~ ARGV[0]' \\
|
|
||||||
-e 'S << [/\#{Regexp.quote($$2)}\\//, "$$(\#{$$1})/"]' \\
|
|
||||||
-e 'ARGV.shift' \\
|
|
||||||
-e 'end' \\
|
|
||||||
-e '}' -e 'S.each(&method(:gsub!))' -- \\
|
|
||||||
'topdir=$(topdir)' 'srcdir=$(srcdir)' 'hdrdir=$(hdrdir)' \\
|
|
||||||
> dep
|
|
||||||
|
|
||||||
include dep
|
|
||||||
EOD
|
|
||||||
}
|
|
||||||
end
|
|
||||||
message "Done.\n"
|
message "Done.\n"
|
||||||
|
|
|
@ -41,7 +41,6 @@ module Buffering
|
||||||
|
|
||||||
def consume_rbuff(size=nil)
|
def consume_rbuff(size=nil)
|
||||||
if @rbuffer.size == 0
|
if @rbuffer.size == 0
|
||||||
@eof = nil
|
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
size = @rbuffer.size unless size
|
size = @rbuffer.size unless size
|
||||||
|
@ -54,6 +53,14 @@ module Buffering
|
||||||
public
|
public
|
||||||
|
|
||||||
def read(size=nil, buf=nil)
|
def read(size=nil, buf=nil)
|
||||||
|
if size == 0
|
||||||
|
if buf
|
||||||
|
buf.clear
|
||||||
|
return buf
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
end
|
||||||
fill_rbuff unless defined? @rbuffer
|
fill_rbuff unless defined? @rbuffer
|
||||||
@eof ||= nil
|
@eof ||= nil
|
||||||
until @eof
|
until @eof
|
||||||
|
@ -68,6 +75,31 @@ module Buffering
|
||||||
(size && ret.empty?) ? nil : ret
|
(size && ret.empty?) ? nil : ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def readpartial(maxlen, buf=nil)
|
||||||
|
if maxlen == 0
|
||||||
|
if buf
|
||||||
|
buf.clear
|
||||||
|
return buf
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if !defined?(@rbuffer) || @rbuffer.size == 0
|
||||||
|
begin
|
||||||
|
return sysread(maxlen, buf)
|
||||||
|
rescue Errno::EAGAIN
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ret = consume_rbuff(maxlen)
|
||||||
|
if buf
|
||||||
|
buf.replace(ret)
|
||||||
|
ret = buf
|
||||||
|
end
|
||||||
|
raise EOFError if ret.empty?
|
||||||
|
ret
|
||||||
|
end
|
||||||
|
|
||||||
def gets(eol=$/)
|
def gets(eol=$/)
|
||||||
fill_rbuff unless defined? @rbuffer
|
fill_rbuff unless defined? @rbuffer
|
||||||
idx = @rbuffer.index(eol)
|
idx = @rbuffer.index(eol)
|
||||||
|
@ -101,13 +133,13 @@ module Buffering
|
||||||
end
|
end
|
||||||
|
|
||||||
def readline(eol=$/)
|
def readline(eol=$/)
|
||||||
raise EOFErorr if eof?
|
raise EOFError if eof?
|
||||||
gets(eol)
|
gets(eol)
|
||||||
end
|
end
|
||||||
|
|
||||||
def getc
|
def getc
|
||||||
c = read(1)
|
c = read(1)
|
||||||
c ? c.to_i : nil
|
c ? c[0] : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def each_byte
|
def each_byte
|
||||||
|
@ -117,7 +149,7 @@ module Buffering
|
||||||
end
|
end
|
||||||
|
|
||||||
def readchar
|
def readchar
|
||||||
raise EOFErorr if eof?
|
raise EOFError if eof?
|
||||||
getc
|
getc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -127,6 +159,7 @@ module Buffering
|
||||||
|
|
||||||
def eof?
|
def eof?
|
||||||
@eof ||= nil
|
@eof ||= nil
|
||||||
|
fill_rbuff if !@eof && (!defined?(@rbuffer) || @rbuffer.size == 0)
|
||||||
@eof && @rbuffer.size == 0
|
@eof && @rbuffer.size == 0
|
||||||
end
|
end
|
||||||
alias eof eof?
|
alias eof eof?
|
||||||
|
@ -144,7 +177,12 @@ module Buffering
|
||||||
remain = idx ? idx + $/.size : @wbuffer.length
|
remain = idx ? idx + $/.size : @wbuffer.length
|
||||||
nwritten = 0
|
nwritten = 0
|
||||||
while remain > 0
|
while remain > 0
|
||||||
nwrote = syswrite(@wbuffer[nwritten,remain])
|
str = @wbuffer[nwritten,remain]
|
||||||
|
begin
|
||||||
|
nwrote = syswrite(str)
|
||||||
|
rescue Errno::EAGAIN
|
||||||
|
retry
|
||||||
|
end
|
||||||
remain -= nwrote
|
remain -= nwrote
|
||||||
nwritten += nwrote
|
nwritten += nwrote
|
||||||
end
|
end
|
||||||
|
@ -166,10 +204,13 @@ module Buffering
|
||||||
|
|
||||||
def puts(*args)
|
def puts(*args)
|
||||||
s = ""
|
s = ""
|
||||||
|
if args.empty?
|
||||||
|
s << "\n"
|
||||||
|
end
|
||||||
args.each{|arg|
|
args.each{|arg|
|
||||||
s << arg.to_s
|
s << arg.to_s
|
||||||
unless /#{$/}\z/o =~ s
|
if $/ && /\n\z/ !~ s
|
||||||
s << $/
|
s << "\n"
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
do_write(s)
|
do_write(s)
|
||||||
|
|
|
@ -433,52 +433,49 @@ ossl_ssl_setup(VALUE self)
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static VALUE
|
||||||
ossl_start_ssl(SSL *ssl, int (*func)())
|
ossl_start_ssl(VALUE self, int (*func)())
|
||||||
{
|
{
|
||||||
|
SSL *ssl;
|
||||||
|
OpenFile *fptr;
|
||||||
|
VALUE cb;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
Data_Get_Struct(self, SSL, ssl);
|
||||||
|
GetOpenFile(ossl_ssl_get_io(self), fptr);
|
||||||
|
cb = ossl_sslctx_get_verify_cb(ossl_ssl_get_ctx(self));
|
||||||
|
SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)cb);
|
||||||
for(;;){
|
for(;;){
|
||||||
if((ret = func(ssl)) > 0) break;
|
if((ret = func(ssl)) > 0) break;
|
||||||
switch(SSL_get_error(ssl, ret)){
|
switch(SSL_get_error(ssl, ret)){
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
rb_io_wait_writable(fptr->fd);
|
||||||
|
continue;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
rb_thread_schedule();
|
rb_io_wait_readable(fptr->fd);
|
||||||
continue;
|
continue;
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
rb_sys_fail(0);
|
||||||
default:
|
default:
|
||||||
ossl_raise(eSSLError, NULL);
|
ossl_raise(eSSLError, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
ossl_ssl_connect(VALUE self)
|
ossl_ssl_connect(VALUE self)
|
||||||
{
|
{
|
||||||
SSL *ssl;
|
|
||||||
VALUE cb;
|
|
||||||
|
|
||||||
ossl_ssl_setup(self);
|
ossl_ssl_setup(self);
|
||||||
Data_Get_Struct(self, SSL, ssl);
|
return ossl_start_ssl(self, SSL_connect);
|
||||||
cb = ossl_sslctx_get_verify_cb(ossl_ssl_get_ctx(self));
|
|
||||||
SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)cb);
|
|
||||||
ossl_start_ssl(ssl, SSL_connect);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
ossl_ssl_accept(VALUE self)
|
ossl_ssl_accept(VALUE self)
|
||||||
{
|
{
|
||||||
SSL *ssl;
|
|
||||||
VALUE cb;
|
|
||||||
|
|
||||||
ossl_ssl_setup(self);
|
ossl_ssl_setup(self);
|
||||||
Data_Get_Struct(self, SSL, ssl);
|
return ossl_start_ssl(self, SSL_accept);
|
||||||
cb = ossl_sslctx_get_verify_cb(ossl_ssl_get_ctx(self));
|
|
||||||
SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)cb);
|
|
||||||
ossl_start_ssl(ssl, SSL_accept);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -512,8 +509,10 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
rb_eof_error();
|
rb_eof_error();
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
rb_io_wait_writable(fptr->fd);
|
||||||
|
continue;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
rb_thread_schedule();
|
rb_io_wait_readable(fptr->fd);
|
||||||
continue;
|
continue;
|
||||||
case SSL_ERROR_SYSCALL:
|
case SSL_ERROR_SYSCALL:
|
||||||
if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
|
if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
|
||||||
|
@ -542,9 +541,11 @@ ossl_ssl_write(VALUE self, VALUE str)
|
||||||
{
|
{
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
int nwrite = 0;
|
int nwrite = 0;
|
||||||
|
OpenFile *fptr;
|
||||||
|
|
||||||
StringValue(str);
|
StringValue(str);
|
||||||
Data_Get_Struct(self, SSL, ssl);
|
Data_Get_Struct(self, SSL, ssl);
|
||||||
|
GetOpenFile(ossl_ssl_get_io(self), fptr);
|
||||||
|
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
for (;;){
|
for (;;){
|
||||||
|
@ -553,11 +554,13 @@ ossl_ssl_write(VALUE self, VALUE str)
|
||||||
case SSL_ERROR_NONE:
|
case SSL_ERROR_NONE:
|
||||||
goto end;
|
goto end;
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
rb_io_wait_writable(fptr->fd);
|
||||||
|
continue;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
rb_thread_schedule();
|
rb_io_wait_readable(fptr->fd);
|
||||||
continue;
|
continue;
|
||||||
case SSL_ERROR_SYSCALL:
|
case SSL_ERROR_SYSCALL:
|
||||||
rb_eof_error();
|
rb_sys_fail(0);
|
||||||
default:
|
default:
|
||||||
ossl_raise(eSSLError, "SSL_write:");
|
ossl_raise(eSSLError, "SSL_write:");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,332 @@
|
||||||
|
begin
|
||||||
|
require "openssl"
|
||||||
|
rescue LoadError
|
||||||
|
end
|
||||||
|
require 'test/unit'
|
||||||
|
|
||||||
|
if defined?(OpenSSL)
|
||||||
|
|
||||||
|
require 'socket'
|
||||||
|
dir = File.expand_path(__FILE__)
|
||||||
|
2.times {dir = File.dirname(dir)}
|
||||||
|
$:.replace([File.join(dir, "ruby")] | $:)
|
||||||
|
require 'ut_eof'
|
||||||
|
|
||||||
|
module SSLPair
|
||||||
|
def server
|
||||||
|
host = "127.0.0.1"
|
||||||
|
port = 0
|
||||||
|
key = OpenSSL::PKey::RSA.new(512)
|
||||||
|
cert = OpenSSL::X509::Certificate.new
|
||||||
|
cert.version = 2
|
||||||
|
cert.serial = 0
|
||||||
|
name = OpenSSL::X509::Name.new([["C","JP"],["O","TEST"],["CN","localhost"]])
|
||||||
|
cert.subject = name
|
||||||
|
cert.issuer = name
|
||||||
|
cert.not_before = Time.now
|
||||||
|
cert.not_after = Time.now + 3600
|
||||||
|
cert.public_key = key.public_key
|
||||||
|
ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
|
||||||
|
cert.extensions = [
|
||||||
|
ef.create_extension("basicConstraints","CA:FALSE"),
|
||||||
|
ef.create_extension("subjectKeyIdentifier","hash"),
|
||||||
|
ef.create_extension("extendedKeyUsage","serverAuth"),
|
||||||
|
ef.create_extension("keyUsage",
|
||||||
|
"keyEncipherment,dataEncipherment,digitalSignature")
|
||||||
|
]
|
||||||
|
ef.issuer_certificate = cert
|
||||||
|
cert.add_extension ef.create_extension("authorityKeyIdentifier",
|
||||||
|
"keyid:always,issuer:always")
|
||||||
|
cert.sign(key, OpenSSL::Digest::SHA1.new)
|
||||||
|
ctx = OpenSSL::SSL::SSLContext.new()
|
||||||
|
ctx.key = key
|
||||||
|
ctx.cert = cert
|
||||||
|
tcps = TCPServer.new(host, port)
|
||||||
|
ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
|
||||||
|
return ssls
|
||||||
|
end
|
||||||
|
|
||||||
|
def client(port)
|
||||||
|
host = "127.0.0.1"
|
||||||
|
ctx = OpenSSL::SSL::SSLContext.new()
|
||||||
|
s = TCPSocket.new(host, port)
|
||||||
|
ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
|
||||||
|
ssl.connect
|
||||||
|
ssl.sync_close = true
|
||||||
|
ssl
|
||||||
|
end
|
||||||
|
|
||||||
|
def ssl_pair
|
||||||
|
ssls = server
|
||||||
|
th = Thread.new {
|
||||||
|
ns = ssls.accept
|
||||||
|
ssls.close
|
||||||
|
ns
|
||||||
|
}
|
||||||
|
port = ssls.to_io.addr[1]
|
||||||
|
c = client(port)
|
||||||
|
s = th.value
|
||||||
|
if block_given?
|
||||||
|
begin
|
||||||
|
yield c, s
|
||||||
|
ensure
|
||||||
|
c.close unless c.closed?
|
||||||
|
s.close unless s.closed?
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return c, s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class OpenSSL::TestEOF1 < Test::Unit::TestCase
|
||||||
|
include TestEOF
|
||||||
|
include SSLPair
|
||||||
|
|
||||||
|
def open_file(content)
|
||||||
|
s1, s2 = ssl_pair
|
||||||
|
Thread.new { s2 << content; s2.close }
|
||||||
|
yield s1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class OpenSSL::TestEOF2 < Test::Unit::TestCase
|
||||||
|
include TestEOF
|
||||||
|
include SSLPair
|
||||||
|
|
||||||
|
def open_file(content)
|
||||||
|
s1, s2 = ssl_pair
|
||||||
|
Thread.new { s1 << content; s1.close }
|
||||||
|
yield s2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class OpenSSL::TestPair < Test::Unit::TestCase
|
||||||
|
include SSLPair
|
||||||
|
|
||||||
|
def test_getc
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s1 << "a"
|
||||||
|
assert_equal(?a, s2.getc)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_readpartial
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s2.write "a\nbcd"
|
||||||
|
assert_equal("a\n", s1.gets)
|
||||||
|
assert_equal("bcd", s1.readpartial(10))
|
||||||
|
s2.write "efg"
|
||||||
|
assert_equal("efg", s1.readpartial(10))
|
||||||
|
s2.close
|
||||||
|
assert_raise(EOFError) { s1.readpartial(10) }
|
||||||
|
assert_raise(EOFError) { s1.readpartial(10) }
|
||||||
|
assert_equal("", s1.readpartial(0))
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_readall
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s2.close
|
||||||
|
assert_equal("", s1.read)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_readline
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s2.close
|
||||||
|
assert_raise(EOFError) { s1.readline }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_puts_meta
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
begin
|
||||||
|
old = $/
|
||||||
|
$/ = '*'
|
||||||
|
s1.puts 'a'
|
||||||
|
ensure
|
||||||
|
$/ = old
|
||||||
|
end
|
||||||
|
s1.close
|
||||||
|
assert_equal("a\n", s2.read)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_puts_empty
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s1.puts
|
||||||
|
s1.close
|
||||||
|
assert_equal("\n", s2.read)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
require "openssl"
|
||||||
|
rescue LoadError
|
||||||
|
end
|
||||||
|
require 'test/unit'
|
||||||
|
|
||||||
|
if defined?(OpenSSL)
|
||||||
|
|
||||||
|
require 'socket'
|
||||||
|
dir = File.expand_path(__FILE__)
|
||||||
|
2.times {dir = File.dirname(dir)}
|
||||||
|
$:.replace([File.join(dir, "ruby")] | $:)
|
||||||
|
require 'ut_eof'
|
||||||
|
|
||||||
|
module SSLPair
|
||||||
|
def server
|
||||||
|
host = "127.0.0.1"
|
||||||
|
port = 0
|
||||||
|
key = OpenSSL::PKey::RSA.new(512)
|
||||||
|
cert = OpenSSL::X509::Certificate.new
|
||||||
|
cert.version = 2
|
||||||
|
cert.serial = 0
|
||||||
|
name = OpenSSL::X509::Name.new([["C","JP"],["O","TEST"],["CN","localhost"]])
|
||||||
|
cert.subject = name
|
||||||
|
cert.issuer = name
|
||||||
|
cert.not_before = Time.now
|
||||||
|
cert.not_after = Time.now + 3600
|
||||||
|
cert.public_key = key.public_key
|
||||||
|
ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
|
||||||
|
cert.extensions = [
|
||||||
|
ef.create_extension("basicConstraints","CA:FALSE"),
|
||||||
|
ef.create_extension("subjectKeyIdentifier","hash"),
|
||||||
|
ef.create_extension("extendedKeyUsage","serverAuth"),
|
||||||
|
ef.create_extension("keyUsage",
|
||||||
|
"keyEncipherment,dataEncipherment,digitalSignature")
|
||||||
|
]
|
||||||
|
ef.issuer_certificate = cert
|
||||||
|
cert.add_extension ef.create_extension("authorityKeyIdentifier",
|
||||||
|
"keyid:always,issuer:always")
|
||||||
|
cert.sign(key, OpenSSL::Digest::SHA1.new)
|
||||||
|
ctx = OpenSSL::SSL::SSLContext.new()
|
||||||
|
ctx.key = key
|
||||||
|
ctx.cert = cert
|
||||||
|
tcps = TCPServer.new(host, port)
|
||||||
|
ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
|
||||||
|
return ssls
|
||||||
|
end
|
||||||
|
|
||||||
|
def client(port)
|
||||||
|
host = "127.0.0.1"
|
||||||
|
ctx = OpenSSL::SSL::SSLContext.new()
|
||||||
|
s = TCPSocket.new(host, port)
|
||||||
|
ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
|
||||||
|
ssl.connect
|
||||||
|
ssl.sync_close = true
|
||||||
|
ssl
|
||||||
|
end
|
||||||
|
|
||||||
|
def ssl_pair
|
||||||
|
ssls = server
|
||||||
|
th = Thread.new {
|
||||||
|
ns = ssls.accept
|
||||||
|
ssls.close
|
||||||
|
ns
|
||||||
|
}
|
||||||
|
port = ssls.to_io.addr[1]
|
||||||
|
c = client(port)
|
||||||
|
s = th.value
|
||||||
|
if block_given?
|
||||||
|
begin
|
||||||
|
yield c, s
|
||||||
|
ensure
|
||||||
|
c.close unless c.closed?
|
||||||
|
s.close unless s.closed?
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return c, s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class OpenSSL::TestEOF1 < Test::Unit::TestCase
|
||||||
|
include TestEOF
|
||||||
|
include SSLPair
|
||||||
|
|
||||||
|
def open_file(content)
|
||||||
|
s1, s2 = ssl_pair
|
||||||
|
Thread.new { s2 << content; s2.close }
|
||||||
|
yield s1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class OpenSSL::TestEOF2 < Test::Unit::TestCase
|
||||||
|
include TestEOF
|
||||||
|
include SSLPair
|
||||||
|
|
||||||
|
def open_file(content)
|
||||||
|
s1, s2 = ssl_pair
|
||||||
|
Thread.new { s1 << content; s1.close }
|
||||||
|
yield s2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class OpenSSL::TestPair < Test::Unit::TestCase
|
||||||
|
include SSLPair
|
||||||
|
|
||||||
|
def test_getc
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s1 << "a"
|
||||||
|
assert_equal(?a, s2.getc)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_readpartial
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s2.write "a\nbcd"
|
||||||
|
assert_equal("a\n", s1.gets)
|
||||||
|
assert_equal("bcd", s1.readpartial(10))
|
||||||
|
s2.write "efg"
|
||||||
|
assert_equal("efg", s1.readpartial(10))
|
||||||
|
s2.close
|
||||||
|
assert_raise(EOFError) { s1.readpartial(10) }
|
||||||
|
assert_raise(EOFError) { s1.readpartial(10) }
|
||||||
|
assert_equal("", s1.readpartial(0))
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_readall
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s2.close
|
||||||
|
assert_equal("", s1.read)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_readline
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s2.close
|
||||||
|
assert_raise(EOFError) { s1.readline }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_puts_meta
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
begin
|
||||||
|
old = $/
|
||||||
|
$/ = '*'
|
||||||
|
s1.puts 'a'
|
||||||
|
ensure
|
||||||
|
$/ = old
|
||||||
|
end
|
||||||
|
s1.close
|
||||||
|
assert_equal("a\n", s2.read)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_puts_empty
|
||||||
|
ssl_pair {|s1, s2|
|
||||||
|
s1.puts
|
||||||
|
s1.close
|
||||||
|
assert_equal("\n", s2.read)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -83,6 +83,32 @@ module TestEOF
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_eof_2
|
||||||
|
open_file("") {|f|
|
||||||
|
assert_equal("", f.read)
|
||||||
|
assert(f.eof?)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_eof_3
|
||||||
|
open_file("") {|f|
|
||||||
|
assert(f.eof?)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_eof_2
|
||||||
|
open_file("") {|f|
|
||||||
|
assert_equal("", f.read)
|
||||||
|
assert(f.eof?)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_eof_3
|
||||||
|
open_file("") {|f|
|
||||||
|
assert(f.eof?)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
module Seek
|
module Seek
|
||||||
def open_file_seek(content, pos)
|
def open_file_seek(content, pos)
|
||||||
open_file(content) do |f|
|
open_file(content) do |f|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче