PJ_DEF(pj_status_t) pjsip_dlg_send_response( pjsip_dialog *dlg,
					     pjsip_transaction *tsx,
					     pjsip_tx_data *tdata)
{
    pj_status_t status;

    /* Sanity check. */
    PJ_ASSERT_RETURN(dlg && tsx && tdata && tdata->msg, PJ_EINVAL);
    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_RESPONSE_MSG,
		     PJSIP_ENOTRESPONSEMSG);

    /* The transaction must belong to this dialog.  */
    PJ_ASSERT_RETURN(tsx->mod_data[dlg->ua->id] == dlg, PJ_EINVALIDOP);

    pj_log_push_indent();

    PJ_LOG(5,(dlg->obj_name, "Sending %s",
	      pjsip_tx_data_get_info(tdata)));

    /* Check that transaction method and cseq match the response.
     * This operation is sloooww (search CSeq header twice), that's why
     * we only do it in debug mode.
     */
#if defined(PJ_DEBUG) && PJ_DEBUG!=0
    PJ_ASSERT_RETURN( PJSIP_MSG_CSEQ_HDR(tdata->msg)->cseq == tsx->cseq &&
		      pjsip_method_cmp(&PJSIP_MSG_CSEQ_HDR(tdata->msg)->method,
				       &tsx->method)==0,
		      PJ_EINVALIDOP);
#endif

    /* Must acquire dialog first, to prevent deadlock */
    pjsip_dlg_inc_lock(dlg);

    /* Last chance to add mandatory headers before the response is
     * sent.
     */
    dlg_beautify_response(dlg, PJ_TRUE, tdata->msg->line.status.code, tdata);

    /* If the dialog is locked to transport, make sure that transaction
     * is locked to the same transport too.
     */
    if (dlg->tp_sel.type != tsx->tp_sel.type ||
	dlg->tp_sel.u.ptr != tsx->tp_sel.u.ptr)
    {
	status = pjsip_tsx_set_transport(tsx, &dlg->tp_sel);
	pj_assert(status == PJ_SUCCESS);
    }

    /* Ask transaction to send the response */
    status = pjsip_tsx_send_msg(tsx, tdata);

    /* This function must decrement transmit data request counter
     * regardless of the operation status. The transaction only
     * decrements the counter if the operation is successful.
     */
    if (status != PJ_SUCCESS) {
	pjsip_tx_data_dec_ref(tdata);
    }

    pjsip_dlg_dec_lock(dlg);
    pj_log_pop_indent();

    return status;
}
PJ_DEF(pj_status_t) pjsip_dlg_send_response( pjsip_dialog *dlg,
					     pjsip_transaction *tsx,
					     pjsip_tx_data *tdata)
{
    pj_status_t status;

     
    PJ_ASSERT_RETURN(dlg && tsx && tdata && tdata->msg, PJ_EINVAL);
    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_RESPONSE_MSG,
		     PJSIP_ENOTRESPONSEMSG);

     
    PJ_ASSERT_RETURN(tsx->mod_data[dlg->ua->id] == dlg, PJ_EINVALIDOP);

    pj_log_push_indent();

    PJ_LOG(5,(dlg->obj_name, "Sending %s",
	      pjsip_tx_data_get_info(tdata)));

     
#if defined(PJ_DEBUG) && PJ_DEBUG!=0
    PJ_ASSERT_RETURN( PJSIP_MSG_CSEQ_HDR(tdata->msg)->cseq == tsx->cseq &&
		      pjsip_method_cmp(&PJSIP_MSG_CSEQ_HDR(tdata->msg)->method,
				       &tsx->method)==0,
		      PJ_EINVALIDOP);
#endif

     
    pjsip_dlg_inc_lock(dlg);

     
    dlg_beautify_response(dlg, PJ_TRUE, tdata->msg->line.status.code, tdata);

     
    if (dlg->tp_sel.type != tsx->tp_sel.type ||
	dlg->tp_sel.u.ptr != tsx->tp_sel.u.ptr)
    {
	status = pjsip_tsx_set_transport(tsx, &dlg->tp_sel);
	pj_assert(status == PJ_SUCCESS);
    }

     
    status = pjsip_tsx_send_msg(tsx, tdata);

     
    if (status != PJ_SUCCESS) {
	pjsip_tx_data_dec_ref(tdata);
    }

    pjsip_dlg_dec_lock(dlg);
    pj_log_pop_indent();

    return status;
}