Index: pjproject/trunk/pjlib/include/pj/ssl_sock.h
===================================================================
--- pjproject/trunk/pjlib/include/pj/ssl_sock.h	(revision 4145)
+++ pjproject/trunk/pjlib/include/pj/ssl_sock.h	(revision 4146)
@@ -543,4 +543,9 @@
     pj_uint32_t		verify_status;
 
+    /**
+     * Last native error returned by the backend.
+     */
+    unsigned long	last_native_err;
+
 } pj_ssl_sock_info;
 
Index: pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c
===================================================================
--- pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c	(revision 4145)
+++ pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c	(revision 4146)
@@ -159,4 +159,6 @@
     pj_status_t		  verify_status;
 
+    unsigned long	  last_err;
+
     pj_sock_t		  sock;
     pj_activesock_t	 *asock;
@@ -213,14 +215,35 @@
 #define PJ_SSL_ERRNO_SPACE_SIZE		PJ_ERRNO_SPACE_SIZE
 
-#define STATUS_FROM_SSL_ERR(err, status) { \
-    status = ERR_GET_LIB(err)*300 + ERR_GET_REASON(err);\
-    pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\
-    if (status) status += PJ_SSL_ERRNO_START;\
-}
-
-#define GET_SSL_STATUS(status) { \
-    unsigned long e = ERR_get_error();\
-    STATUS_FROM_SSL_ERR(e, status);\
-}
+/* Expected maximum value of reason component in OpenSSL error code */
+#define MAX_OSSL_ERR_REASON		1200
+
+static pj_status_t STATUS_FROM_SSL_ERR(pj_ssl_sock_t *ssock,
+				       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
+     * if it exceeds the space, only the error reason will be kept.
+     * Note that the last native error will be kept as is and can be
+     * retrieved via SSL socket info.
+     */
+    status = ERR_GET_LIB(err)*MAX_OSSL_ERR_REASON + ERR_GET_REASON(err);
+    if (status > PJ_SSL_ERRNO_SPACE_SIZE)
+	status = ERR_GET_REASON(err);
+
+    status += PJ_SSL_ERRNO_START;
+    ssock->last_err = err;
+    return status;
+}
+
+static pj_status_t GET_SSL_STATUS(pj_ssl_sock_t *ssock)
+{
+    return STATUS_FROM_SSL_ERR(ssock, ERR_get_error());
+}
+
 
 /*
@@ -236,6 +259,6 @@
 	unsigned long l, r;
 	ssl_err -= PJ_SSL_ERRNO_START;
-	l = ssl_err/300;
-	r = ssl_err%300;
+	l = ssl_err / MAX_OSSL_ERR_REASON;
+	r = ssl_err % MAX_OSSL_ERR_REASON;
 	ssl_err = ERR_PACK(l, 0, r);
     }
@@ -245,10 +268,5 @@
     {
 	const char *tmp = NULL;
-
-	if (ssl_err >= 300)
-	    tmp = ERR_reason_error_string(ssl_err);
-	else
-	    tmp = X509_verify_cert_error_string(ssl_err);
-
+	tmp = ERR_reason_error_string(ssl_err);
 	if (tmp) {
 	    pj_ansi_strncpy(buf, tmp, bufsize);
@@ -518,6 +536,5 @@
     ctx = SSL_CTX_new(ssl_method);
     if (ctx == NULL) {
-	GET_SSL_STATUS(status);
-	return status;
+	return GET_SSL_STATUS(ssock);
     }
 
@@ -530,5 +547,5 @@
 
 	    if (rc != 1) {
-		GET_SSL_STATUS(status);
+		status = GET_SSL_STATUS(ssock);
 		PJ_LOG(1,(ssock->pool->obj_name, "Error loading CA list file "
 			  "'%s'", cert->CA_file.ptr));
@@ -552,5 +569,5 @@
 
 	    if(rc != 1) {
-		GET_SSL_STATUS(status);
+		status = GET_SSL_STATUS(ssock);
 		PJ_LOG(1,(ssock->pool->obj_name, "Error loading certificate "
 			  "chain file '%s'", cert->cert_file.ptr));
@@ -568,5 +585,5 @@
 
 	    if(rc != 1) {
-		GET_SSL_STATUS(status);
+		status = GET_SSL_STATUS(ssock);
 		PJ_LOG(1,(ssock->pool->obj_name, "Error adding private key "
 			  "from '%s'", cert->privkey_file.ptr));
@@ -581,6 +598,5 @@
     ssock->ossl_ssl = SSL_new(ssock->ossl_ctx);
     if (ssock->ossl_ssl == NULL) {
-	GET_SSL_STATUS(status);
-	return status;
+	return GET_SSL_STATUS(ssock);
     }
 
@@ -714,7 +730,5 @@
     ret = SSL_set_cipher_list(ssock->ossl_ssl, buf);
     if (ret < 1) {
-	pj_status_t status;
-	GET_SSL_STATUS(status);
-	return status;
+	return GET_SSL_STATUS(ssock);
     }
 
@@ -1021,4 +1035,11 @@
 	 */
 	if (status != PJ_SUCCESS) {
+	    /* Server disconnected us, possibly due to SSL nego failure */
+	    if (status == PJ_EEOF) {
+		unsigned long err;
+		err = ERR_get_error();
+		if (err != SSL_ERROR_NONE)
+		    status = STATUS_FROM_SSL_ERR(ssock, err);
+	    }
 	    reset_ssl_sock_state(ssock);
 	}
@@ -1197,14 +1218,4 @@
     /* Perform SSL handshake */
     err = SSL_do_handshake(ssock->ossl_ssl);
-    if (err < 0) {
-	err = SSL_get_error(ssock->ossl_ssl, err);
-	if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ) 
-	{
-	    /* Handshake fails */
-	    GET_SSL_STATUS(status);
-	    pj_lock_release(ssock->write_mutex);
-	    return status;
-	}
-    }
 
     /* SSL_do_handshake() may put some pending data into SSL write BIO, 
@@ -1219,4 +1230,14 @@
     pj_lock_release(ssock->write_mutex);
 
+    if (err < 0) {
+	err = SSL_get_error(ssock->ossl_ssl, err);
+	if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ) 
+	{
+	    /* Handshake fails */
+	    status = STATUS_FROM_SSL_ERR(ssock, err);
+	    return status;
+	}
+    }
+
     /* Check if handshake has been completed */
     if (SSL_is_init_finished(ssock->ossl_ssl)) {
@@ -1250,5 +1271,5 @@
 	nwritten = BIO_write(ssock->ossl_rbio, data, size);
 	if (nwritten < size) {
-	    GET_SSL_STATUS(status);
+	    status = GET_SSL_STATUS(ssock);
 	    goto on_error;
 	}
@@ -1324,5 +1345,5 @@
 		{
 		    /* Reset SSL socket state, then return PJ_FALSE */
-		    GET_SSL_STATUS(status);
+		    status = STATUS_FROM_SSL_ERR(ssock, err);
 		    reset_ssl_sock_state(ssock);
 		    goto on_error;
@@ -1905,4 +1926,7 @@
 	info->verify_status = ssock->verify_status;
     }
+
+    /* Last known OpenSSL error code */
+    info->last_native_err = ssock->last_err;
 
     return PJ_SUCCESS;
@@ -2052,5 +2076,5 @@
 	} else {
 	    /* Some problem occured */
-	    GET_SSL_STATUS(status);
+	    status = STATUS_FROM_SSL_ERR(ssock, err);
 	}
     } else {
@@ -2379,5 +2403,5 @@
     ret = SSL_renegotiate(ssock->ossl_ssl);
     if (ret <= 0) {
-	GET_SSL_STATUS(status);
+	status = GET_SSL_STATUS(ssock);
     } else {
 	status = do_handshake(ssock);
Index: pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c	(revision 4145)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c	(revision 4146)
@@ -195,7 +195,19 @@
     if (state_cb) {
 	pjsip_transport_state_info state_info;
-
+	pjsip_tls_state_info tls_info;
+	pj_ssl_sock_info ssl_info;
+	
+	/* Init transport state info */
 	pj_bzero(&state_info, sizeof(state_info));
 	state_info.status = tls->close_reason;
+
+	if (tls->ssock && 
+	    pj_ssl_sock_get_info(tls->ssock, &ssl_info) == PJ_SUCCESS)
+	{
+	    pj_bzero(&tls_info, sizeof(tls_info));
+	    tls_info.ssl_sock_info = &ssl_info;
+	    state_info.ext_info = &tls_info;
+	}
+
 	(*state_cb)(&tls->base, PJSIP_TP_STATE_DISCONNECTED, &state_info);
     }
