From 2429393218565767f5dd934c2c54fe4d21baf605 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Mon, 30 Sep 2013 22:40:39 +0100 Subject: [PATCH 1/3] improved ssl write error handling...this hopefully fixes occasionally crashes when using ssl --- src/server/close_conn.c | 1 + src/stream/write.c | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/server/close_conn.c b/src/server/close_conn.c index 33d2dd4..ab5d9d1 100644 --- a/src/server/close_conn.c +++ b/src/server/close_conn.c @@ -39,6 +39,7 @@ serverCloseConn(Server this, unsigned int i) if (NULL != st && STREAM_SSL == st->type) { SSL_shutdown((st->handle).ssl); SSL_free((st->handle).ssl); + (st->handle).ssl = NULL; } delete(st); diff --git a/src/stream/write.c b/src/stream/write.c index f8e5899..edfc5e6 100644 --- a/src/stream/write.c +++ b/src/stream/write.c @@ -63,12 +63,34 @@ streamWrite(Stream this, void * buf, size_t count) break; case STREAM_SSL: + /* + * @TODO I got a segfault in this call under unclear + * circumstances. Most likely it has to do with a + * write on a closed connection. + */ done = SSL_write((this->handle).ssl, buf, count); if (0 >= done) { switch (SSL_get_error((this->handle).ssl, done)) { - case SSL_ERROR_SSL: case SSL_ERROR_SYSCALL: + { + switch (errno) { + case EINTR: + case ENOBUFS: + case ENOMEM: + done = 0; + break; + case (EAGAIN|EWOULDBLOCK): + done = -1; + break; + default: + done = -2; + break; + } + } + break; + + case SSL_ERROR_SSL: { unsigned long err; @@ -82,6 +104,7 @@ streamWrite(Stream this, void * buf, size_t count) // DROP THROUGH case SSL_ERROR_ZERO_RETURN: + default: done = -2; break; } From d1f4c39dcd13b8f22ac1d104e78e6d7d3b513dc9 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Mon, 30 Sep 2013 22:44:37 +0100 Subject: [PATCH 2/3] and do the same when read --- src/stream/read.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/stream/read.c b/src/stream/read.c index 9b697f5..2db19ae 100644 --- a/src/stream/read.c +++ b/src/stream/read.c @@ -68,8 +68,25 @@ streamRead(Stream this, void * buf, size_t count) if (0 >= done) { switch (SSL_get_error((this->handle).ssl, done)) { + case SSL_ERROR_SYSCALL: + { + switch (errno) { + case EINTR: + case ENOBUFS: + case ENOMEM: + done = 0; + break; + case (EAGAIN|EWOULDBLOCK): + done = -1; + break; + default: + done = -2; + break; + } + } + break; + case SSL_ERROR_SSL: - case SSL_ERROR_SYSCALL: { unsigned long err; @@ -83,6 +100,7 @@ streamRead(Stream this, void * buf, size_t count) // DROP THROUGH case SSL_ERROR_ZERO_RETURN: + default: done = -2; break; } From 69692587055fefe65e930817ec3d45dbc9378cee Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Mon, 30 Sep 2013 22:59:11 +0100 Subject: [PATCH 3/3] fix the fix...with the last change taskrambler closes connections unexpectedly. Hopefully this fixes ssl handling. --- src/stream/read.c | 9 +++++---- src/stream/write.c | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/stream/read.c b/src/stream/read.c index 2db19ae..7bfbdca 100644 --- a/src/stream/read.c +++ b/src/stream/read.c @@ -66,7 +66,9 @@ streamRead(Stream this, void * buf, size_t count) case STREAM_SSL: done = SSL_read((this->handle).ssl, buf, count); - if (0 >= done) { + if (0 == done) { + done = -2; + } else if (0 > done) { switch (SSL_get_error((this->handle).ssl, done)) { case SSL_ERROR_SYSCALL: { @@ -80,7 +82,7 @@ streamRead(Stream this, void * buf, size_t count) done = -1; break; default: - done = -2; + done = -1; break; } } @@ -100,7 +102,6 @@ streamRead(Stream this, void * buf, size_t count) // DROP THROUGH case SSL_ERROR_ZERO_RETURN: - default: done = -2; break; } @@ -109,7 +110,7 @@ streamRead(Stream this, void * buf, size_t count) break; default: - done = 0; + done = -2; break; } diff --git a/src/stream/write.c b/src/stream/write.c index edfc5e6..00aa9aa 100644 --- a/src/stream/write.c +++ b/src/stream/write.c @@ -70,7 +70,9 @@ streamWrite(Stream this, void * buf, size_t count) */ done = SSL_write((this->handle).ssl, buf, count); - if (0 >= done) { + if (0 == done) { + done = -2; + } else if (0 > done) { switch (SSL_get_error((this->handle).ssl, done)) { case SSL_ERROR_SYSCALL: { @@ -104,7 +106,6 @@ streamWrite(Stream this, void * buf, size_t count) // DROP THROUGH case SSL_ERROR_ZERO_RETURN: - default: done = -2; break; } @@ -113,7 +114,7 @@ streamWrite(Stream this, void * buf, size_t count) break; default: - done = 0; + done = -2; break; }