PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
					const pj_ssl_sock_param *param,
					pj_ssl_sock_t **p_ssock)
{
    pj_ssl_sock_t *ssock;
    pj_status_t status;
    pj_pool_t *info_pool;

    PJ_ASSERT_RETURN(pool && param && p_ssock, PJ_EINVAL);
    PJ_ASSERT_RETURN(param->sock_type == pj_SOCK_STREAM(), PJ_ENOTSUP);

    info_pool = pj_pool_create(pool->factory, "ssl_chain%p", 512, 512, NULL);
    pool = pj_pool_create(pool->factory, "ssl%p", 512, 512, NULL);

    /* Create secure socket */
    ssock = ssl_alloc(pool);
    if (!ssock)
    	return PJ_ENOMEM;
    ssock->pool = pool;
    ssock->info_pool = info_pool;
    ssock->sock = PJ_INVALID_SOCKET;
    ssock->ssl_state = SSL_STATE_NULL;
    ssock->circ_buf_input.owner = ssock;
    ssock->circ_buf_output.owner = ssock;
    pj_list_init(&ssock->write_pending);
    pj_list_init(&ssock->write_pending_empty);
    pj_list_init(&ssock->send_pending);
    pj_timer_entry_init(&ssock->timer, 0, ssock, &on_timer);
    pj_ioqueue_op_key_init(&ssock->handshake_op_key,
			   sizeof(pj_ioqueue_op_key_t));
    pj_ioqueue_op_key_init(&ssock->shutdown_op_key,
			   sizeof(pj_ioqueue_op_key_t));

    /* Create secure socket mutex */
    status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
                                            &ssock->circ_buf_output_mutex);
    ssock->write_mutex = ssock->circ_buf_output_mutex;
    if (status != PJ_SUCCESS)
        return status;

    /* Create input circular buffer mutex */
    status = pj_lock_create_simple_mutex(pool, pool->obj_name,
                                         &ssock->circ_buf_input_mutex);
    if (status != PJ_SUCCESS)
        return status;

    /* Init secure socket param */
    pj_ssl_sock_param_copy(pool, &ssock->param, param);

    if (ssock->param.grp_lock) {
	pj_grp_lock_add_ref(ssock->param.grp_lock);
	pj_grp_lock_add_handler(ssock->param.grp_lock, pool, ssock,
				ssl_on_destroy);
    }

    ssock->param.read_buffer_size = ((ssock->param.read_buffer_size+7)>>3)<<3;
    if (!ssock->param.timer_heap) {
	PJ_LOG(3,(ssock->pool->obj_name, "Warning: timer heap is not "
		  "available. It is recommended to supply one to avoid "
	          "a race condition if more than one worker threads "
	          "are used."));
    }

    /* Finally */
    *p_ssock = ssock;

    return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
					const pj_ssl_sock_param *param,
					pj_ssl_sock_t **p_ssock)
{
    pj_ssl_sock_t *ssock;
    pj_status_t status;
    pj_pool_t *info_pool;

    PJ_ASSERT_RETURN(pool && param && p_ssock, PJ_EINVAL);
    PJ_ASSERT_RETURN(param->sock_type == pj_SOCK_STREAM(), PJ_ENOTSUP);

    info_pool = pj_pool_create(pool->factory, "ssl_chain%p", 512, 512, NULL);
    pool = pj_pool_create(pool->factory, "ssl%p", 512, 512, NULL);

     
    ssock = ssl_alloc(pool);
    if (!ssock)
    	return PJ_ENOMEM;
    ssock->pool = pool;
    ssock->info_pool = info_pool;
    ssock->sock = PJ_INVALID_SOCKET;
    ssock->ssl_state = SSL_STATE_NULL;
    ssock->circ_buf_input.owner = ssock;
    ssock->circ_buf_output.owner = ssock;
    pj_list_init(&ssock->write_pending);
    pj_list_init(&ssock->write_pending_empty);
    pj_list_init(&ssock->send_pending);
    pj_timer_entry_init(&ssock->timer, 0, ssock, &on_timer);
    pj_ioqueue_op_key_init(&ssock->handshake_op_key,
			   sizeof(pj_ioqueue_op_key_t));
    pj_ioqueue_op_key_init(&ssock->shutdown_op_key,
			   sizeof(pj_ioqueue_op_key_t));

     
    status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
                                            &ssock->circ_buf_output_mutex);
    ssock->write_mutex = ssock->circ_buf_output_mutex;
    if (status != PJ_SUCCESS)
        return status;

     
    status = pj_lock_create_simple_mutex(pool, pool->obj_name,
                                         &ssock->circ_buf_input_mutex);
    if (status != PJ_SUCCESS)
        return status;

     
    pj_ssl_sock_param_copy(pool, &ssock->param, param);

    if (ssock->param.grp_lock) {
	pj_grp_lock_add_ref(ssock->param.grp_lock);
	pj_grp_lock_add_handler(ssock->param.grp_lock, pool, ssock,
				ssl_on_destroy);
    }

    ssock->param.read_buffer_size = ((ssock->param.read_buffer_size+7)>>3)<<3;
    if (!ssock->param.timer_heap) {
	PJ_LOG(3,(ssock->pool->obj_name, "Warning: timer heap is not "
		  "available. It is recommended to supply one to avoid "
	          "a race condition if more than one worker threads "
	          "are used."));
    }

     
    *p_ssock = ssock;

    return PJ_SUCCESS;
}