summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/openssl/lib/openssl/buffering.rb21
-rw-r--r--ext/openssl/ossl_ssl.c136
2 files changed, 69 insertions, 88 deletions
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 5dabcd5135..095ab248ce 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -99,6 +99,27 @@ module Buffering
ret
end
+ def read_nonblock(maxlen, buf=nil)
+ if maxlen == 0
+ if buf
+ buf.clear
+ return buf
+ else
+ return ""
+ end
+ end
+ if @rbuffer.empty?
+ return sysread_nonblock(maxlen, buf)
+ end
+ ret = consume_rbuff(maxlen)
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ raise EOFError if ret.empty?
+ ret
+ end
+
def gets(eol=$/, limit=nil)
idx = @rbuffer.index(eol)
until @eof
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index c4959dd6e7..310e0c5783 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -12,14 +12,6 @@
*/
#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
@@ -999,82 +991,8 @@ ossl_ssl_accept(VALUE self)
return ossl_start_ssl(self, SSL_accept, "SSL_accept");
}
-/*
- * call-seq:
- * ssl.sysread(length) => string
- * ssl.sysread(length, buffer) => buffer
- *
- * === Parameters
- * * +length+ is a positive integer.
- * * +buffer+ is a string used to store the result.
- */
static VALUE
-ossl_ssl_read(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);
- if (ssl) {
- if(SSL_pending(ssl) <= 0)
- rb_thread_wait_fd(FPTR_TO_FD(fptr));
- 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_io_wait_readable(FPTR_TO_FD(fptr));
- 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("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)
+ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
{
SSL *ssl;
int ilen, nread = 0;
@@ -1093,20 +1011,29 @@ ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
Data_Get_Struct(self, SSL, ssl);
GetOpenFile(ossl_ssl_get_io(self), fptr);
- rb_io_set_nonblock(fptr);
if (ssl) {
+ if(!nonblock && SSL_pending(ssl) <= 0)
+ rb_thread_wait_fd(FPTR_TO_FD(fptr));
for (;;){
nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
- 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:
+ if (nonblock) {
+ errno = EWOULDBLOCK;
+ rb_sys_fail(0);
+ }
rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- rb_sys_fail_path(fptr->pathv);
+ if (nonblock) {
+ errno = EWOULDBLOCK;
+ rb_sys_fail(0);
+ }
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
@@ -1117,8 +1044,9 @@ ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
}
}
else {
+ ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
rb_warning("SSL session is not started yet.");
- return rb_funcall(ossl_ssl_get_io(self), rb_intern("sysread"), 2, len, str);
+ return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
}
end:
@@ -1128,6 +1056,38 @@ ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
return str;
}
+
+/*
+ * call-seq:
+ * ssl.sysread(length) => string
+ * ssl.sysread(length, buffer) => buffer
+ *
+ * === Parameters
+ * * +length+ is a positive integer.
+ * * +buffer+ is a string used to store the result.
+ */
+static VALUE
+ossl_ssl_read(int argc, VALUE *argv, VALUE self)
+{
+ return ossl_ssl_read_internal(argc, argv, self, 0);
+}
+
+/*
+ * call-seq:
+ * ssl.sysread_nonblock(length) => string
+ * ssl.sysread_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)
+{
+ return ossl_ssl_read_internal(argc, argv, self, 1);
+}
+
+
/*
* call-seq:
* ssl.syswrite(string) => integer
@@ -1490,9 +1450,9 @@ Init_ossl_ssl()
rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
+ rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -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);