diff --git a/lib/roles/http/client/client.c b/lib/roles/http/client/client.c
index 214b7be2e157501dee9a78c9fc8ade5c349162a1..6732625401b41b57d7666d55f456c026a10c1e63 100644
--- a/lib/roles/http/client/client.c
+++ b/lib/roles/http/client/client.c
@@ -1117,10 +1117,7 @@ lws_http_client_read(struct lws *wsi, char **buf, int *len)
 		return -1;
 	}
 
-	if (rlen == 0)
-		return -1;
-
-	if (rlen < 0)
+	if (rlen <= 0)
 		return 0;
 
 	*len = rlen;
@@ -1140,7 +1137,7 @@ spin_chunks:
 			}
 			n = char_to_hex((*buf)[0]);
 			if (n < 0) {
-				lwsl_debug("chunking failure\n");
+				lwsl_info("%s: chunking failure\n", __func__);
 				return -1;
 			}
 			wsi->chunk_remaining <<= 4;
@@ -1148,7 +1145,7 @@ spin_chunks:
 			break;
 		case ELCP_CR:
 			if ((*buf)[0] != '\x0a') {
-				lwsl_debug("chunking failure\n");
+				lwsl_info("%s: chunking failure\n", __func__);
 				return -1;
 			}
 			wsi->chunk_parser = ELCP_CONTENT;
@@ -1163,7 +1160,7 @@ spin_chunks:
 
 		case ELCP_POST_CR:
 			if ((*buf)[0] != '\x0d') {
-				lwsl_debug("chunking failure\n");
+				lwsl_info("%s: chunking failure\n", __func__);
 
 				return -1;
 			}
@@ -1172,8 +1169,11 @@ spin_chunks:
 			break;
 
 		case ELCP_POST_LF:
-			if ((*buf)[0] != '\x0a')
+			if ((*buf)[0] != '\x0a') {
+				lwsl_info("%s: chunking failure\n", __func__);
+
 				return -1;
+			}
 
 			wsi->chunk_parser = ELCP_HEX;
 			wsi->chunk_remaining = 0;
@@ -1208,7 +1208,7 @@ spin_chunks:
 		if (user_callback_handle_rxflow(wsi_eff->protocol->callback,
 				wsi_eff, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
 				wsi_eff->user_space, *buf, n)) {
-			lwsl_debug("%s: RECEIVE_CLIENT_HTTP_READ returned -1\n",
+			lwsl_info("%s: RECEIVE_CLIENT_HTTP_READ returned -1\n",
 				   __func__);
 
 			return -1;
diff --git a/lib/tls/openssl/ssl.c b/lib/tls/openssl/ssl.c
index 2af4a7af9f39431e50d9368ddefa78f920a6153c..8e25a1753e581a4242a9bc7a97ba9d12953f8ad9 100644
--- a/lib/tls/openssl/ssl.c
+++ b/lib/tls/openssl/ssl.c
@@ -226,19 +226,49 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
 
 
 	lwsl_debug("%p: SSL_read says %d\n", wsi, n);
-	/* manpage: returning 0 means connection shut down */
-	if (!n || (n == -1 && errno == LWS_ENOTCONN)) {
-		wsi->socket_is_permanently_unusable = 1;
+	/* manpage: returning 0 means connection shut down
+	 *
+	 * 2018-09-10: https://github.com/openssl/openssl/issues/1903
+	 *
+	 * So, in summary, if you get a 0 or -1 return from SSL_read() /
+	 * SSL_write(), you should call SSL_get_error():
+	 *
+	 *  - If you get back SSL_ERROR_RETURN_ZERO then you know the connection
+	 *    has been cleanly shutdown by the peer. To fully close the
+	 *    connection you may choose to call SSL_shutdown() to send a
+	 *    close_notify back.
+	 *
+	 *  - If you get back SSL_ERROR_SSL then some kind of internal or
+	 *    protocol error has occurred. More details will be on the SSL error
+	 *    queue. You can also call SSL_get_shutdown(). If this indicates a
+	 *    state of SSL_RECEIVED_SHUTDOWN then you know a fatal alert has
+	 *    been received from the peer (if it had been a close_notify then
+	 *    SSL_get_error() would have returned SSL_ERROR_RETURN_ZERO).
+	 *    SSL_ERROR_SSL is considered fatal - you should not call
+	 *    SSL_shutdown() in this case.
+	 *
+	 *  - If you get back SSL_ERROR_SYSCALL then some kind of fatal (i.e.
+	 *    non-retryable) error has occurred in a system call.
+	 */
+	if (n <= 0) {
+		m = lws_ssl_get_error(wsi, n);
+		lwsl_notice("%p: ssl err %d errno %d\n", wsi, m, errno);
+		if (m == SSL_ERROR_ZERO_RETURN) /* cleanly shut down */
+			return LWS_SSL_CAPABLE_ERROR;
 
-		return LWS_SSL_CAPABLE_ERROR;
-	}
+		/* hm not retryable.. could be 0 size pkt or error  */
+
+		if (m == SSL_ERROR_SSL || m == SSL_ERROR_SYSCALL ||
+		    errno == LWS_ENOTCONN) {
+
+			/* unclean, eg closed conn */
+
+			wsi->socket_is_permanently_unusable = 1;
 
-	if (n < 0) {
-		m = lws_ssl_get_error(wsi, n);
-		lwsl_debug("%p: ssl err %d errno %d\n", wsi, m, errno);
-		if (m == SSL_ERROR_ZERO_RETURN ||
-		    m == SSL_ERROR_SYSCALL)
 			return LWS_SSL_CAPABLE_ERROR;
+		}
+
+		/* retryable? */
 
 		if (SSL_want_read(wsi->tls.ssl)) {
 			lwsl_debug("%s: WANT_READ\n", __func__);
@@ -250,9 +280,8 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
 			lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
 			return LWS_SSL_CAPABLE_MORE_SERVICE;
 		}
-		wsi->socket_is_permanently_unusable = 1;
 
-		return LWS_SSL_CAPABLE_ERROR;
+		/* keep on trucking it seems */
 	}
 
 	lws_stats_atomic_bump(context, pt, LWSSTATS_B_READ, n);