Index: pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c
===================================================================
--- pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c	(revision 5630)
+++ pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c	(revision 5631)
@@ -299,12 +299,102 @@
 #define MAX_OSSL_ERR_REASON		1200
 
-static pj_status_t STATUS_FROM_SSL_ERR(pj_ssl_sock_t *ssock,
-				       unsigned long err)
+
+static char *SSLErrorString (int err)
+{
+    switch (err) {
+    case SSL_ERROR_NONE:
+	return "SSL_ERROR_NONE";
+    case SSL_ERROR_ZERO_RETURN:
+	return "SSL_ERROR_ZERO_RETURN";
+    case SSL_ERROR_WANT_READ:
+	return "SSL_ERROR_WANT_READ";
+    case SSL_ERROR_WANT_WRITE:
+	return "SSL_ERROR_WANT_WRITE";
+    case SSL_ERROR_WANT_CONNECT:
+	return "SSL_ERROR_WANT_CONNECT";
+    case SSL_ERROR_WANT_ACCEPT:
+	return "SSL_ERROR_WANT_ACCEPT";
+    case SSL_ERROR_WANT_X509_LOOKUP:
+	return "SSL_ERROR_WANT_X509_LOOKUP";
+    case SSL_ERROR_SYSCALL:
+	return "SSL_ERROR_SYSCALL";
+    case SSL_ERROR_SSL:
+	return "SSL_ERROR_SSL";
+    default:
+	return "SSL_ERROR_UNKNOWN";
+    }
+}
+
+#define ERROR_LOG(msg, err) \
+    PJ_LOG(2,("SSL", "%s (%s): Level: %d err: <%lu> <%s-%s-%s> len: %d", \
+	      msg, action, level, err, \
+	      (ERR_lib_error_string(err)? ERR_lib_error_string(err): "???"), \
+	      (ERR_func_error_string(err)? ERR_func_error_string(err):"???"),\
+	      (ERR_reason_error_string(err)? \
+	       ERR_reason_error_string(err): "???"), len));
+
+static void SSLLogErrors(char * action, int ret, int ssl_err, int len)
+{
+    char *ssl_err_str = SSLErrorString(ssl_err);
+
+    if (!action) {
+	action = "UNKNOWN";
+    }
+
+    switch (ssl_err) {
+    case SSL_ERROR_SYSCALL:
+    {
+	unsigned long err2 = ERR_get_error();
+	if (err2) {
+	    int level = 0;
+	    while (err2) {
+	        ERROR_LOG("SSL_ERROR_SYSCALL", err2);
+		level++;
+		err2 = ERR_get_error();
+	    }
+	} else if (ret == 0) {
+	    /* An EOF was observed that violates the protocol */
+
+	    /* The TLS/SSL handshake was not successful but was shut down
+	     * controlled and by the specifications of the TLS/SSL protocol.
+	     */
+	} else if (ret == -1) {
+	    /* BIO error - look for more info in errno... */
+	    char errStr[250] = "";
+	    strerror_r(errno, errStr, sizeof(errStr));
+	    /* for now - continue logging these if they occur.... */
+	    PJ_LOG(4,("SSL", "BIO error, SSL_ERROR_SYSCALL (%s): "
+	    		     "errno: <%d> <%s> len: %d",
+		      	     action, errno, errStr, len));
+	} else {
+	    /* ret!=0 & ret!=-1 & nothing on error stack - is this valid??? */
+	    PJ_LOG(2,("SSL", "SSL_ERROR_SYSCALL (%s) ret: %d len: %d",
+		      action, ret, len));
+	}
+	break;
+    }
+    case SSL_ERROR_SSL:
+    {
+	unsigned long err2 = ERR_get_error();
+	int level = 0;
+
+	while (err2) {
+	    ERROR_LOG("SSL_ERROR_SSL", err2);
+	    level++;
+	    err2 = ERR_get_error();
+	}
+	break;
+    }
+    default:
+	PJ_LOG(2,("SSL", "%lu [%s] (%s) ret: %d len: %d",
+		  ssl_err, ssl_err_str, action, ret, len));
+	break;
+    }
+}
+
+
+static pj_status_t GET_STATUS_FROM_SSL_ERR(unsigned long err)
 {
     pj_status_t status;
-
-    /* General SSL error, dig more from OpenSSL error queue */
-    if (err == SSL_ERROR_SSL)
-	err = ERR_get_error();
 
     /* OpenSSL error range is much wider than PJLIB errno space, so
@@ -318,11 +408,47 @@
 
     status += PJ_SSL_ERRNO_START;
+    return status;
+}
+
+/* err contains ERR_get_error() status */
+static pj_status_t STATUS_FROM_SSL_ERR(char *action, pj_ssl_sock_t *ssock,
+				       unsigned long err)
+{
+    int level = 0;
+    int len = 0; //dummy
+
+    ERROR_LOG("STATUS_FROM_SSL_ERR", err);
+    level++;
+
+    /* General SSL error, dig more from OpenSSL error queue */
+    if (err == SSL_ERROR_SSL) {
+	err = ERR_get_error();
+	ERROR_LOG("STATUS_FROM_SSL_ERR", err);
+    }
+
     ssock->last_err = err;
-    return status;
+    return GET_STATUS_FROM_SSL_ERR(err);
+}
+
+/* err contains SSL_get_error() status */
+static pj_status_t STATUS_FROM_SSL_ERR2(char *action, pj_ssl_sock_t *ssock,
+					int ret, int err, int len)
+{
+    unsigned long ssl_err = err;
+
+    if (err == SSL_ERROR_SSL) {
+	ssl_err = ERR_peek_error();
+    }
+
+    /* Dig for more from OpenSSL error queue */
+    SSLLogErrors(action, ret, err, len);
+
+    ssock->last_err = ssl_err;
+    return GET_STATUS_FROM_SSL_ERR(ssl_err);
 }
 
 static pj_status_t GET_SSL_STATUS(pj_ssl_sock_t *ssock)
 {
-    return STATUS_FROM_SSL_ERR(ssock, ERR_get_error());
+    return STATUS_FROM_SSL_ERR("status", ssock, ERR_get_error());
 }
 
@@ -1515,5 +1641,5 @@
 		err = ERR_get_error();
 		if (err != SSL_ERROR_NONE)
-		    status = STATUS_FROM_SSL_ERR(ssock, err);
+		    status = STATUS_FROM_SSL_ERR("connecting", ssock, err);
 	    }
 	    reset_ssl_sock_state(ssock);
@@ -1834,9 +1960,9 @@
 
     if (err < 0) {
-	err = SSL_get_error(ssock->ossl_ssl, err);
-	if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ) 
+	int err2 = SSL_get_error(ssock->ossl_ssl, err);
+	if (err2 != SSL_ERROR_NONE && err2 != SSL_ERROR_WANT_READ)
 	{
 	    /* Handshake fails */
-	    status = STATUS_FROM_SSL_ERR(ssock, err);
+	    status = STATUS_FROM_SSL_ERR2("Handshake", ssock, err, err2, 0);
 	    return status;
 	}
@@ -1914,4 +2040,5 @@
 	    void *data_ = (pj_int8_t*)buf->data + buf->len;
 	    int size_ = (int)(ssock->read_size - buf->len);
+	    int len = size_;
 
 	    /* SSL_read() may write some data to BIO write when re-negotiation
@@ -1966,8 +2093,20 @@
 		if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
 		{
-		    /* Reset SSL socket state, then return PJ_FALSE */
-		    status = STATUS_FROM_SSL_ERR(ssock, err);
-		    reset_ssl_sock_state(ssock);
-		    goto on_error;
+		    if (err == SSL_ERROR_SYSCALL && size_ == -1 &&
+			ERR_peek_error() == 0 && errno == 0)
+		    {
+			status = STATUS_FROM_SSL_ERR2("Read", ssock, size_,
+						      err, len);
+			PJ_LOG(4,("SSL", "SSL_read() = -1, with "
+				  	 "SSL_ERROR_SYSCALL, no SSL error, "
+				  	 "and errno = 0 - skip BIO error"));
+		        /* Ignore these errors */
+		    } else {
+		        /* Reset SSL socket state, then return PJ_FALSE */
+		        status = STATUS_FROM_SSL_ERR2("Read", ssock, size_,
+		        			      err, len);
+		        reset_ssl_sock_state(ssock);
+		        goto on_error;
+		    }
 		}
 
@@ -2857,5 +2996,5 @@
 	} else {
 	    /* Some problem occured */
-	    status = STATUS_FROM_SSL_ERR(ssock, err);
+	    status = STATUS_FROM_SSL_ERR2("Write", ssock, nwritten, err, size);
 	}
     } else {
