aboutsummaryrefslogtreecommitdiffstats
path: root/ext
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-11-28 02:57:37 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-11-28 03:16:05 +0900
commitdbf433ef04ff98bc619930c9202a517e19c0e57e (patch)
tree5ced9174a5cd9c63a9dcfa0527ac0873d18bc775 /ext
parentc1dd6b096f5174e1d57584e603f58a0a76a9db43 (diff)
downloadruby-openssl-dbf433ef04ff98bc619930c9202a517e19c0e57e.tar.gz
ssl: inline ossl_ssl_shutdown() into ossl_ssl_stop()
We call SSL_shutdown() four times at most meaninglessly. Since the underlying socket is in non-blocking mode, if the first call failed because the underlying socket is not write/readable, the subsequent calls would just fail with the same error. Just call once, and give up if it fails.
Diffstat (limited to 'ext')
-rw-r--r--ext/openssl/ossl_ssl.c35
1 files changed, 15 insertions, 20 deletions
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 6931e998..b8874b84 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1373,24 +1373,6 @@ ssl_started(SSL *ssl)
}
static void
-ossl_ssl_shutdown(SSL *ssl)
-{
- int i;
-
- /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */
- /* It says max 2x pending + 2x data = 4 */
- for (i = 0; i < 4; ++i) {
- /*
- * Ignore the case SSL_shutdown returns -1. Empty handshake_func
- * must not happen.
- */
- if (SSL_shutdown(ssl) != 0)
- break;
- }
- ossl_clear_error();
-}
-
-static void
ossl_ssl_free(void *ssl)
{
SSL_free(ssl);
@@ -1873,11 +1855,24 @@ static VALUE
ossl_ssl_stop(VALUE self)
{
SSL *ssl;
+ int ret;
GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ return Qnil;
+ ret = SSL_shutdown(ssl);
+ if (ret == 1) /* Have already received close_notify */
+ return Qnil;
+ if (ret == 0) /* Sent close_notify, but we don't wait for reply */
+ return Qnil;
- ossl_ssl_shutdown(ssl);
-
+ /*
+ * XXX: Something happened. Possibly it failed because the underlying socket
+ * is not writable/readable, since it is in non-blocking mode. We should do
+ * some proper error handling using SSL_get_error() and maybe retry, but we
+ * can't block here. Give up for now.
+ */
+ ossl_clear_error();
return Qnil;
}