static pj_bool_t ssock_on_data_read (pj_ssl_sock_t *ssock,
				     void *data,
				     pj_size_t size,
				     pj_status_t status,
				     pj_size_t *remainder)
{
    if (status != PJ_SUCCESS)
    	goto on_error;

    if (data && size > 0) {
    	pj_status_t status_;

	/* Consume the whole data */
        if (ssock->circ_buf_input_mutex)
	    pj_lock_acquire(ssock->circ_buf_input_mutex);
        status_ = io_write(ssock,&ssock->circ_buf_input, data, size);
        if (ssock->circ_buf_input_mutex)
            pj_lock_release(ssock->circ_buf_input_mutex);
        if (status_ != PJ_SUCCESS) {
            status = status_;
	    goto on_error;
	}
    }

    /* Check if SSL handshake hasn't finished yet */
    if (ssock->ssl_state == SSL_STATE_HANDSHAKING) {
	pj_bool_t ret = PJ_TRUE;

	if (status == PJ_SUCCESS)
	    status = ssl_do_handshake(ssock);

	/* Not pending is either success or failed */
	if (status != PJ_EPENDING)
	    ret = on_handshake_complete(ssock, status);

	return ret;
    }

    /* See if there is any decrypted data for the application */
    if (ssock->read_started) {
	do {
	    read_data_t *buf = *(OFFSET_OF_READ_DATA_PTR(ssock, data));
	    void *data_ = (pj_int8_t*)buf->data + buf->len;
	    int size_ = (int)(ssock->read_size - buf->len);
	    pj_status_t status_;

	    status_ = ssl_read(ssock, data_, &size_);

	    if (size_ > 0 || status != PJ_SUCCESS) {
		if (ssock->param.cb.on_data_read) {
		    pj_bool_t ret;
		    pj_size_t remainder_ = 0;

		    if (size_ > 0)
			buf->len += size_;
    		
                    if (status != PJ_SUCCESS) {
                        ssock->ssl_state = SSL_STATE_ERROR;
                    }

		    ret = (*ssock->param.cb.on_data_read)(ssock, buf->data,
							  buf->len, status,
							  &remainder_);
		    if (!ret) {
			/* We've been destroyed */
			return PJ_FALSE;
		    }

		    /* Application may have left some data to be consumed 
		     * later.
		     */
		    buf->len = remainder_;
		}

		/* Active socket signalled connection closed/error, this has
		 * been signalled to the application along with any remaining
		 * buffer. So, let's just reset SSL socket now.
		 */
		if (status != PJ_SUCCESS) {
		    ssl_reset_sock_state(ssock);
		    return PJ_FALSE;
		}

	    } else if (status_ == PJ_SUCCESS) {
	    	break;
	    } else if (status_ == PJ_EEOF) {
		status = ssl_do_handshake(ssock);
		if (status == PJ_SUCCESS) {
		    /* Renegotiation completed */

		    /* Update certificates */
		    ssl_update_certs_info(ssock);

		    // Ticket #1573: Don't hold mutex while calling
		    //               PJLIB socket send(). 
		    //pj_lock_acquire(ssock->write_mutex);
		    status = flush_delayed_send(ssock);
		    //pj_lock_release(ssock->write_mutex);

		    /* If flushing is ongoing, treat it as success */
		    if (status == PJ_EBUSY)
			status = PJ_SUCCESS;

		    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
			PJ_PERROR(1,(ssock->pool->obj_name, status, 
				     "Failed to flush delayed send"));
			goto on_error;
		    }
		} else if (status != PJ_EPENDING) {
		    PJ_PERROR(1,(ssock->pool->obj_name, status, 
			         "Renegotiation failed"));
		    goto on_error;
		}

		break;
	    } else {
	    	/* Error */
	    	status = status_;
	    	goto on_error;
	    }

	} while (1);
    }

    return PJ_TRUE;

on_error:
    if (ssock->ssl_state == SSL_STATE_HANDSHAKING)
	return on_handshake_complete(ssock, status);

    if (ssock->read_started && ssock->param.cb.on_data_read) {
	pj_bool_t ret;
	ret = (*ssock->param.cb.on_data_read)(ssock, NULL, 0, status,
					      remainder);
	if (!ret) {
	    /* We've been destroyed */
	    return PJ_FALSE;
	}
    }

    ssl_reset_sock_state(ssock);
    return PJ_FALSE;
}
static pj_bool_t ssock_on_data_read (pj_ssl_sock_t *ssock,
				     void *data,
				     pj_size_t size,
				     pj_status_t status,
				     pj_size_t *remainder)
{
    if (status != PJ_SUCCESS)
    	goto on_error;

    if (data && size > 0) {
    	pj_status_t status_;

	 
        if (ssock->circ_buf_input_mutex)
	    pj_lock_acquire(ssock->circ_buf_input_mutex);
        status_ = io_write(ssock,&ssock->circ_buf_input, data, size);
        if (ssock->circ_buf_input_mutex)
            pj_lock_release(ssock->circ_buf_input_mutex);
        if (status_ != PJ_SUCCESS) {
            status = status_;
	    goto on_error;
	}
    }

     
    if (ssock->ssl_state == SSL_STATE_HANDSHAKING) {
	pj_bool_t ret = PJ_TRUE;

	if (status == PJ_SUCCESS)
	    status = ssl_do_handshake(ssock);

	 
	if (status != PJ_EPENDING)
	    ret = on_handshake_complete(ssock, status);

	return ret;
    }

     
    if (ssock->read_started) {
	do {
	    read_data_t *buf = *(OFFSET_OF_READ_DATA_PTR(ssock, data));
	    void *data_ = (pj_int8_t*)buf->data + buf->len;
	    int size_ = (int)(ssock->read_size - buf->len);
	    pj_status_t status_;

	    status_ = ssl_read(ssock, data_, &size_);

	    if (size_ > 0 || status != PJ_SUCCESS) {
		if (ssock->param.cb.on_data_read) {
		    pj_bool_t ret;
		    pj_size_t remainder_ = 0;

		    if (size_ > 0)
			buf->len += size_;
    		
                    if (status != PJ_SUCCESS) {
                        ssock->ssl_state = SSL_STATE_ERROR;
                    }

		    ret = (*ssock->param.cb.on_data_read)(ssock, buf->data,
							  buf->len, status,
							  &remainder_);
		    if (!ret) {
			 
			return PJ_FALSE;
		    }

		     
		    buf->len = remainder_;
		}

		 
		if (status != PJ_SUCCESS) {
		    ssl_reset_sock_state(ssock);
		    return PJ_FALSE;
		}

	    } else if (status_ == PJ_SUCCESS) {
	    	break;
	    } else if (status_ == PJ_EEOF) {
		status = ssl_do_handshake(ssock);
		if (status == PJ_SUCCESS) {
		     

		     
		    ssl_update_certs_info(ssock);

		     
		     
		     
		    status = flush_delayed_send(ssock);
		     

		     
		    if (status == PJ_EBUSY)
			status = PJ_SUCCESS;

		    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
			PJ_PERROR(1,(ssock->pool->obj_name, status, 
				     "Failed to flush delayed send"));
			goto on_error;
		    }
		} else if (status != PJ_EPENDING) {
		    PJ_PERROR(1,(ssock->pool->obj_name, status, 
			         "Renegotiation failed"));
		    goto on_error;
		}

		break;
	    } else {
	    	 
	    	status = status_;
	    	goto on_error;
	    }

	} while (1);
    }

    return PJ_TRUE;

on_error:
    if (ssock->ssl_state == SSL_STATE_HANDSHAKING)
	return on_handshake_complete(ssock, status);

    if (ssock->read_started && ssock->param.cb.on_data_read) {
	pj_bool_t ret;
	ret = (*ssock->param.cb.on_data_read)(ssock, NULL, 0, status,
					      remainder);
	if (!ret) {
	     
	    return PJ_FALSE;
	}
    }

    ssl_reset_sock_state(ssock);
    return PJ_FALSE;
}