summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorgotoyuzo <gotoyuzo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-03-07 12:10:03 +0000
committergotoyuzo <gotoyuzo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-03-07 12:10:03 +0000
commit24cb3707eb4abc3060e234cb0927edde3ff0b0ad (patch)
tree4faf09890511fce6f2f2d54b7af5a7f9ca18515f /ext
parent64eaecb8a8e79c63f4dfa88f8b6bed1d7d9fcd51 (diff)
* ext/openssl/ossl_ssl.c (ossl_start_ssl, ossl_ssl_read,
ossl_ssl_write): - need to set errno on Win32 platform. - should call rb_sys_fail instead of rasing SSLError if SSL_ERROR_SYSCALL occured. - 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/lib/openssl/buffering.rb (Buffering#initialize): should set @eof and @rbuffer. (Buffering#fill_rbuff): should rescue Errno::EAGAIN. (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#each): fix typo. suggested by Brian Ollenberger. (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/lib/openssl/ssl.rb: set non-blocking flag to the underlying IO. * 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/branches/ruby_1_8@8104 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/openssl/extconf.rb28
-rw-r--r--ext/openssl/lib/openssl/buffering.rb71
-rw-r--r--ext/openssl/lib/openssl/ssl.rb11
-rw-r--r--ext/openssl/ossl_ssl.c71
4 files changed, 107 insertions, 74 deletions
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index d587116c82..4517ec82fb 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -113,33 +113,5 @@ have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h")
have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
message "=== Checking done. ===\n"
-$distcleanfiles << "GNUmakefile" << "dep"
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"
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 31dcdf1f9a..bd11afe043 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -20,6 +20,8 @@ module Buffering
BLOCK_SIZE = 1024*16
def initialize(*args)
+ @eof = false
+ @rbuffer = ""
@sync = @io.sync
end
@@ -29,17 +31,17 @@ module Buffering
private
def fill_rbuff
- @rbuffer = "" unless defined? @rbuffer
begin
@rbuffer << self.sysread(BLOCK_SIZE)
+ rescue Errno::EAGAIN
+ retry
rescue EOFError
@eof = true
end
end
def consume_rbuff(size=nil)
- if @rbuffer.size == 0
- @eof = nil
+ if @rbuffer.empty?
nil
else
size = @rbuffer.size unless size
@@ -52,8 +54,14 @@ module Buffering
public
def read(size=nil, buf=nil)
- fill_rbuff unless defined? @rbuffer
- @eof ||= nil
+ if size == 0
+ if buf
+ buf.clear
+ else
+ buf = ""
+ end
+ return @eof ? nil : buf
+ end
until @eof
break if size && size <= @rbuffer.size
fill_rbuff
@@ -66,10 +74,33 @@ module Buffering
(size && ret.empty?) ? nil : ret
end
+ def readpartial(maxlen, buf=nil)
+ if maxlen == 0
+ if buf
+ buf.clear
+ else
+ buf = ""
+ end
+ return @eof ? nil : buf
+ end
+ if @rbuffer.empty?
+ 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=$/)
- fill_rbuff unless defined? @rbuffer
idx = @rbuffer.index(eol)
- @eof ||= nil
until @eof
break if idx
fill_rbuff
@@ -84,7 +115,7 @@ module Buffering
end
def each(eol=$/)
- while line = self.gets(eol?)
+ while line = self.gets(eol)
yield line
end
end
@@ -99,13 +130,13 @@ module Buffering
end
def readline(eol=$/)
- raise EOFErorr if eof?
+ raise EOFError if eof?
gets(eol)
end
def getc
c = read(1)
- c ? c.to_i : nil
+ c ? c[0] : nil
end
def each_byte
@@ -115,7 +146,7 @@ module Buffering
end
def readchar
- raise EOFErorr if eof?
+ raise EOFError if eof?
getc
end
@@ -124,8 +155,8 @@ module Buffering
end
def eof?
- @eof ||= nil
- @eof && @rbuffer.size == 0
+ fill_rbuff if !@eof && @rbuffer.empty?
+ @eof && @rbuffer.empty?
end
alias eof eof?
@@ -142,7 +173,12 @@ module Buffering
remain = idx ? idx + $/.size : @wbuffer.length
nwritten = 0
while remain > 0
- nwrote = syswrite(@wbuffer[nwritten,remain])
+ str = @wbuffer[nwritten,remain]
+ begin
+ nwrote = syswrite(str)
+ rescue Errno::EAGAIN
+ retry
+ end
remain -= nwrote
nwritten += nwrote
end
@@ -164,10 +200,13 @@ module Buffering
def puts(*args)
s = ""
+ if args.empty?
+ s << "\n"
+ end
args.each{|arg|
s << arg.to_s
- unless /#{$/}\z/o =~ s
- s << $/
+ if $/ && /\n\z/ !~ s
+ s << "\n"
end
}
do_write(s)
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index 9c31fa73cd..441890865b 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -16,6 +16,7 @@
require "openssl"
require "openssl/buffering"
+require "fcntl"
module OpenSSL
module SSL
@@ -49,9 +50,19 @@ module OpenSSL
end
end
+ module Nonblock
+ def initialize(*args)
+ flag = File::NONBLOCK
+ flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
+ @io.fcntl(Fcntl::F_SETFL, flag)
+ super
+ end
+ end
+
class SSLSocket
include Buffering
include SocketForwarder
+ include Nonblock
def post_connection_check(hostname)
check_common_name = true
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index c73a160a94..01b44f3210 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -433,52 +433,56 @@ ossl_ssl_setup(VALUE self)
return Qtrue;
}
-static void
-ossl_start_ssl(SSL *ssl, int (*func)())
+#ifdef _WIN32
+#define ssl_get_error(ssl, ret) \
+ (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
+#else
+#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
+#endif
+
+static VALUE
+ossl_start_ssl(VALUE self, int (*func)())
{
+ SSL *ssl;
+ OpenFile *fptr;
+ VALUE cb;
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(;;){
if((ret = func(ssl)) > 0) break;
- switch(SSL_get_error(ssl, ret)){
+ switch(ssl_get_error(ssl, ret)){
case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(fileno(fptr->f));
+ continue;
case SSL_ERROR_WANT_READ:
- rb_thread_schedule();
- continue;
+ rb_io_wait_readable(fileno(fptr->f));
+ continue;
+ case SSL_ERROR_SYSCALL:
+ rb_sys_fail(0);
default:
ossl_raise(eSSLError, NULL);
}
}
+
+ return self;
}
static VALUE
ossl_ssl_connect(VALUE self)
{
- SSL *ssl;
- VALUE cb;
-
ossl_ssl_setup(self);
- Data_Get_Struct(self, SSL, ssl);
- 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;
+ return ossl_start_ssl(self, SSL_connect);
}
static VALUE
ossl_ssl_accept(VALUE self)
{
- SSL *ssl;
- VALUE cb;
-
ossl_ssl_setup(self);
- Data_Get_Struct(self, SSL, ssl);
- 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;
+ return ossl_start_ssl(self, SSL_accept);
}
static VALUE
@@ -506,18 +510,20 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
rb_thread_wait_fd(fileno(fptr->f));
for (;;){
nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
- switch(SSL_get_error(ssl, nread)){
+ switch(ssl_get_error(ssl, nread)){
case SSL_ERROR_NONE:
goto end;
case SSL_ERROR_ZERO_RETURN:
rb_eof_error();
case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(fileno(fptr->f));
+ continue;
case SSL_ERROR_WANT_READ:
- rb_thread_schedule();
+ rb_io_wait_readable(fileno(fptr->f));
continue;
case SSL_ERROR_SYSCALL:
if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
- ossl_raise(eSSLError, "SSL_read: %s", strerror(errno));
+ rb_sys_fail(0);
default:
ossl_raise(eSSLError, "SSL_read:");
}
@@ -542,21 +548,26 @@ ossl_ssl_write(VALUE self, VALUE str)
{
SSL *ssl;
int nwrite = 0;
- FILE *fp;
+ OpenFile *fptr;
StringValue(str);
Data_Get_Struct(self, SSL, ssl);
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
if (ssl) {
for (;;){
nwrite = SSL_write(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
- switch(SSL_get_error(ssl, nwrite)){
+ switch(ssl_get_error(ssl, nwrite)){
case SSL_ERROR_NONE:
goto end;
case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(fileno(fptr->f));
+ continue;
case SSL_ERROR_WANT_READ:
- rb_thread_schedule();
- continue;
+ rb_io_wait_readable(fileno(fptr->f));
+ continue;
+ case SSL_ERROR_SYSCALL:
+ rb_sys_fail(0);
default:
ossl_raise(eSSLError, "SSL_write:");
}