/**************** THE TEST ******************/
static void run_job(job_t *j)
{
    pjsip_inv_session *inv;
    pjsip_tx_data *tdata;
    pjmedia_sdp_session *sdp;
    pj_status_t status;

    if (j->who == PJSIP_ROLE_UAC)
	inv = inv_test.uac;
    else
	inv = inv_test.uas;

    switch (j->type) {
    case SEND_OFFER:
	sdp = create_sdp(inv->dlg->pool, oa_sdp[inv_test.oa_index].offer);

	TRACE_((THIS_FILE, "    Sending UPDATE with offer"));
	status = pjsip_inv_update(inv, NULL, sdp, &tdata);
	pj_assert(status == PJ_SUCCESS);

	status = pjsip_inv_send_msg(inv, tdata);
	pj_assert(status == PJ_SUCCESS);
	break;
    case ESTABLISH_CALL:
	TRACE_((THIS_FILE, "    Sending 200/OK"));
	status = pjsip_inv_answer(inv, 200, NULL, NULL, &tdata);
	pj_assert(status == PJ_SUCCESS);

	status = pjsip_inv_send_msg(inv, tdata);
	pj_assert(status == PJ_SUCCESS);
	break;
    }
}
static pj_bool_t on_rx_request(pjsip_rx_data *rdata)
{
    if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG &&
	rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD)
    {
	pjsip_dialog *dlg;
	pjmedia_sdp_session *sdp = NULL;
	pj_str_t uri;
	pjsip_tx_data *tdata;
	pj_status_t status;

	/*
	 * Create UAS
	 */
	uri = pj_str(CONTACT);
	status = pjsip_dlg_create_uas_and_inc_lock(pjsip_ua_instance(), rdata,
						   &uri, &dlg);
	pj_assert(status == PJ_SUCCESS);

	if (inv_test.param.oa[0] == OFFERER_UAC)
	    sdp = create_sdp(rdata->tp_info.pool, oa_sdp[0].answer);
	else if (inv_test.param.oa[0] == OFFERER_UAS)
	    sdp = create_sdp(rdata->tp_info.pool, oa_sdp[0].offer);
	else
	    pj_assert(!"Invalid offerer type");

	status = pjsip_inv_create_uas(dlg, rdata, sdp, inv_test.param.inv_option, &inv_test.uas);
	pj_assert(status == PJ_SUCCESS);
	pjsip_dlg_dec_lock(dlg);

	TRACE_((THIS_FILE, "    Sending 183 with SDP"));

	/*
	 * Answer with 183
	 */
	status = pjsip_inv_initial_answer(inv_test.uas, rdata, 183, NULL,
					  NULL, &tdata);
	pj_assert(status == PJ_SUCCESS);

	status = pjsip_inv_send_msg(inv_test.uas, tdata);
	pj_assert(status == PJ_SUCCESS);

	return PJ_TRUE;
    }

    return PJ_FALSE;
}
/**************** INVITE SESSION CALLBACKS ******************/
static void on_rx_offer(pjsip_inv_session *inv,
			const pjmedia_sdp_session *offer)
{
    pjmedia_sdp_session *sdp;

    PJ_UNUSED_ARG(offer);

    sdp = create_sdp(inv->dlg->pool, oa_sdp[inv_test.oa_index].answer);
    pjsip_inv_set_sdp_answer(inv, sdp);

    if (inv_test.oa_index == inv_test.param.count-1 &&
	inv_test.param.need_established) 
    {
	jobs[job_cnt].type = ESTABLISH_CALL;
	jobs[job_cnt].who = PJSIP_ROLE_UAS;
	job_cnt++;
    }
}
static int perform_test(inv_test_param_t *param)
{
    pj_str_t uri;
    pjsip_dialog *dlg;
    pjmedia_sdp_session *sdp;
    pjsip_tx_data *tdata;
    pj_status_t status;

    PJ_LOG(3,(THIS_FILE, "  %s", param->title));

    pj_bzero(&inv_test, sizeof(inv_test));
    pj_memcpy(&inv_test.param, param, sizeof(*param));
    job_cnt = 0;

    uri = pj_str(CONTACT);

    /*  
     * Create UAC
     */
    status = pjsip_dlg_create_uac(pjsip_ua_instance(), 
				  &uri, &uri, &uri, &uri, &dlg);
    PJ_ASSERT_RETURN(status==PJ_SUCCESS, -10);

    if (inv_test.param.oa[0] == OFFERER_UAC)
	sdp = create_sdp(dlg->pool, oa_sdp[0].offer);
    else
	sdp = NULL;

    status = pjsip_inv_create_uac(dlg, sdp, inv_test.param.inv_option, &inv_test.uac);
    PJ_ASSERT_RETURN(status==PJ_SUCCESS, -20);

    TRACE_((THIS_FILE, "    Sending INVITE %s offer", (sdp ? "with" : "without")));

    /*
     * Make call!
     */
    status = pjsip_inv_invite(inv_test.uac, &tdata);
    PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);

    status = pjsip_inv_send_msg(inv_test.uac, tdata);
    PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);

    /*
     * Wait until test completes
     */
    while (!inv_test.complete) {
	pj_time_val delay = {0, 20};

	pjsip_endpt_handle_events(endpt, &delay);

	while (job_cnt) {
	    job_t j;

	    j = jobs[0];
	    pj_array_erase(jobs, sizeof(jobs[0]), job_cnt, 0);
	    --job_cnt;

	    run_job(&j);
	}
    }

    flush_events(100);

    /*
     * Hangup
     */
    TRACE_((THIS_FILE, "    Disconnecting call"));
    status = pjsip_inv_end_session(inv_test.uas, PJSIP_SC_DECLINE, 0, &tdata);
    pj_assert(status == PJ_SUCCESS);

    status = pjsip_inv_send_msg(inv_test.uas, tdata);
    pj_assert(status == PJ_SUCCESS);

    flush_events(500);

    return 0;
}