mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* ext/openssl/ossl_ssl.c (ossl_ssl_read_nonblock):
OpenSSL::SSL::SSLSocket should implement read_nonblock. a patch from Aaron Patterson in [ruby-core:20277]. fix: #814 [ruby-core:20241] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20493 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									8a8226fa3b
								
							
						
					
					
						commit
						57f7d8c2cd
					
				
					 3 changed files with 99 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,9 @@
 | 
			
		|||
Thu Dec  4 16:19:18 2008  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* ext/openssl/ossl_ssl.c (ossl_ssl_read_nonblock):
 | 
			
		||||
	  OpenSSL::SSL::SSLSocket should implement read_nonblock.  a patch
 | 
			
		||||
	  from Aaron Patterson in [ruby-core:20277].  fix: #814 [ruby-core:20241]
 | 
			
		||||
 | 
			
		||||
Thu Dec  4 16:16:09 2008  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* lib/gserver.rb: fixed type in sample code.  a report from Oleg
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,14 @@
 | 
			
		|||
 */
 | 
			
		||||
#include "ossl.h"
 | 
			
		||||
 | 
			
		||||
#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_FCNTL_H) || defined(_WIN32)
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#elif defined(HAVE_SYS_FCNTL_H)
 | 
			
		||||
#include <sys/fcntl.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_UNISTD_H)
 | 
			
		||||
#  include <unistd.h> /* for read(), and write() */
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1045,9 +1053,72 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
        ID id_sysread = rb_intern("sysread");
 | 
			
		||||
    rb_warning("SSL session is not started yet.");
 | 
			
		||||
        return rb_funcall(ossl_ssl_get_io(self), id_sysread, 2, len, str);
 | 
			
		||||
    return rb_funcall(ossl_ssl_get_io(self), rb_intern("read_nonblock"), 2, len, str);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
end:
 | 
			
		||||
  rb_str_set_len(str, nread);
 | 
			
		||||
  OBJ_TAINT(str);
 | 
			
		||||
 | 
			
		||||
  return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * call-seq:
 | 
			
		||||
 *    ssl.read_nonblock(length) => string
 | 
			
		||||
 *    ssl.read_nonblock(length, buffer) => buffer
 | 
			
		||||
 *
 | 
			
		||||
 * === Parameters
 | 
			
		||||
 * * +length+ is a positive integer.
 | 
			
		||||
 * * +buffer+ is a string used to store the result.
 | 
			
		||||
 */
 | 
			
		||||
static VALUE
 | 
			
		||||
ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
 | 
			
		||||
{
 | 
			
		||||
    SSL *ssl;
 | 
			
		||||
    int ilen, nread = 0;
 | 
			
		||||
    VALUE len, str;
 | 
			
		||||
    rb_io_t *fptr;
 | 
			
		||||
 | 
			
		||||
    rb_scan_args(argc, argv, "11", &len, &str);
 | 
			
		||||
    ilen = NUM2INT(len);
 | 
			
		||||
    if(NIL_P(str)) str = rb_str_new(0, ilen);
 | 
			
		||||
    else{
 | 
			
		||||
        StringValue(str);
 | 
			
		||||
        rb_str_modify(str);
 | 
			
		||||
        rb_str_resize(str, ilen);
 | 
			
		||||
    }
 | 
			
		||||
    if(ilen == 0) return str;
 | 
			
		||||
 | 
			
		||||
    Data_Get_Struct(self, SSL, ssl);
 | 
			
		||||
    GetOpenFile(ossl_ssl_get_io(self), fptr);
 | 
			
		||||
    rb_io_set_nonblock(fptr);
 | 
			
		||||
    if (ssl) {
 | 
			
		||||
	for (;;){
 | 
			
		||||
	    nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
 | 
			
		||||
	    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(FPTR_TO_FD(fptr));
 | 
			
		||||
                continue;
 | 
			
		||||
	    case SSL_ERROR_WANT_READ:
 | 
			
		||||
	        rb_sys_fail_path(fptr->pathv);
 | 
			
		||||
		continue;
 | 
			
		||||
	    case SSL_ERROR_SYSCALL:
 | 
			
		||||
		if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
 | 
			
		||||
		rb_sys_fail(0);
 | 
			
		||||
	    default:
 | 
			
		||||
		ossl_raise(eSSLError, "SSL_read:");
 | 
			
		||||
	    }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        rb_warning("SSL session is not started yet.");
 | 
			
		||||
        return rb_funcall(ossl_ssl_get_io(self), rb_intern("sysread"), 2, len, str);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  end:
 | 
			
		||||
| 
						 | 
				
			
			@ -1421,6 +1492,7 @@ Init_ossl_ssl()
 | 
			
		|||
    rb_define_method(cSSLSocket, "sysread",    ossl_ssl_read, -1);
 | 
			
		||||
    rb_define_method(cSSLSocket, "syswrite",   ossl_ssl_write, 1);
 | 
			
		||||
    rb_define_method(cSSLSocket, "sysclose",   ossl_ssl_close, 0);
 | 
			
		||||
    rb_define_method(cSSLSocket, "read_nonblock",    ossl_ssl_read_nonblock, -1);
 | 
			
		||||
    rb_define_method(cSSLSocket, "cert",       ossl_ssl_get_cert, 0);
 | 
			
		||||
    rb_define_method(cSSLSocket, "peer_cert",  ossl_ssl_get_peer_cert, 0);
 | 
			
		||||
    rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -166,6 +166,21 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
 | 
			
		|||
    assert_equal(ctx.setup, nil)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_ssl_read_nonblock
 | 
			
		||||
    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) { |server, port|
 | 
			
		||||
      sock = TCPSocket.new("127.0.0.1", port)
 | 
			
		||||
      ssl = OpenSSL::SSL::SSLSocket.new(sock)
 | 
			
		||||
      ssl.sync_close = true
 | 
			
		||||
      ssl.connect
 | 
			
		||||
      assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { ssl.read_nonblock(100) }
 | 
			
		||||
      ssl.write("abc\n")
 | 
			
		||||
      IO.select [ssl]
 | 
			
		||||
      assert_equal('a', ssl.read_nonblock(1))
 | 
			
		||||
      assert_equal("bc\n", ssl.read_nonblock(100))
 | 
			
		||||
      assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { ssl.read_nonblock(100) }
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_connect_and_close
 | 
			
		||||
    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
 | 
			
		||||
      sock = TCPSocket.new("127.0.0.1", port)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue