PJ_DEF(pj_status_t) pjsip_dlg_send_request( pjsip_dialog *dlg,
					    pjsip_tx_data *tdata,
					    int mod_data_id,
					    void *mod_data)
{
    pjsip_transaction *tsx;
    pjsip_msg *msg = tdata->msg;
    pj_status_t status;

    /* Check arguments. */
    PJ_ASSERT_RETURN(dlg && tdata && tdata->msg, PJ_EINVAL);
    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG,
		     PJSIP_ENOTREQUESTMSG);

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

    /* Lock and increment session */
    pjsip_dlg_inc_lock(dlg);

    /* Put this dialog in tdata's mod_data */
    tdata->mod_data[dlg->ua->id] = dlg;

    /* If via_addr is set, use this address for the Via header. */
    if (dlg->via_addr.host.slen > 0) {
        tdata->via_addr = dlg->via_addr;
        tdata->via_tp = dlg->via_tp;
    }

    /* Update dialog's CSeq and message's CSeq if request is not
     * ACK nor CANCEL.
     */
    if (msg->line.req.method.id != PJSIP_CANCEL_METHOD &&
	msg->line.req.method.id != PJSIP_ACK_METHOD)
    {
	pjsip_cseq_hdr *ch;

	ch = PJSIP_MSG_CSEQ_HDR(msg);
	PJ_ASSERT_RETURN(ch!=NULL, PJ_EBUG);

	ch->cseq = dlg->local.cseq++;

	/* Force the whole message to be re-printed. */
	pjsip_tx_data_invalidate_msg( tdata );
    }

    /* Create a new transaction if method is not ACK.
     * The transaction user is the user agent module.
     */
    if (msg->line.req.method.id != PJSIP_ACK_METHOD) {
	int tsx_count;

	status = pjsip_tsx_create_uac(dlg->ua, tdata, &tsx);
	if (status != PJ_SUCCESS)
	    goto on_error;

	/* Set transport selector */
	status = pjsip_tsx_set_transport(tsx, &dlg->tp_sel);
	pj_assert(status == PJ_SUCCESS);

	/* Attach this dialog to the transaction, so that user agent
	 * will dispatch events to this dialog.
	 */
	tsx->mod_data[dlg->ua->id] = dlg;

	/* Copy optional caller's mod_data, if present */
	if (mod_data_id >= 0 && mod_data_id < PJSIP_MAX_MODULE)
	    tsx->mod_data[mod_data_id] = mod_data;

	/* Increment transaction counter. */
	tsx_count = ++dlg->tsx_count;

	/* Send the message. */
	status = pjsip_tsx_send_msg(tsx, tdata);
	if (status != PJ_SUCCESS) {
	    if (dlg->tsx_count == tsx_count)
		pjsip_tsx_terminate(tsx, tsx->status_code);
	    goto on_error;
	}

    } else {
	/* Set transport selector */
	pjsip_tx_data_set_transport(tdata, &dlg->tp_sel);

	/* Send request */
	status = pjsip_endpt_send_request_stateless(dlg->endpt, tdata,
						    NULL, &send_ack_callback);
	if (status != PJ_SUCCESS)
	    goto on_error;

    }

    /* Unlock dialog, may destroy dialog. */
    pjsip_dlg_dec_lock(dlg);
    pj_log_pop_indent();
    return PJ_SUCCESS;

on_error:
    /* Unlock dialog, may destroy dialog. */
    pjsip_dlg_dec_lock(dlg);

    /* Whatever happen delete the message. */
    pjsip_tx_data_dec_ref( tdata );
    pj_log_pop_indent();
    return status;
}
PJ_DEF(pj_status_t) pjsip_dlg_send_request( pjsip_dialog *dlg,
					    pjsip_tx_data *tdata,
					    int mod_data_id,
					    void *mod_data)
{
    pjsip_transaction *tsx;
    pjsip_msg *msg = tdata->msg;
    pj_status_t status;

     
    PJ_ASSERT_RETURN(dlg && tdata && tdata->msg, PJ_EINVAL);
    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG,
		     PJSIP_ENOTREQUESTMSG);

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

     
    pjsip_dlg_inc_lock(dlg);

     
    tdata->mod_data[dlg->ua->id] = dlg;

     
    if (dlg->via_addr.host.slen > 0) {
        tdata->via_addr = dlg->via_addr;
        tdata->via_tp = dlg->via_tp;
    }

     
    if (msg->line.req.method.id != PJSIP_CANCEL_METHOD &&
	msg->line.req.method.id != PJSIP_ACK_METHOD)
    {
	pjsip_cseq_hdr *ch;

	ch = PJSIP_MSG_CSEQ_HDR(msg);
	PJ_ASSERT_RETURN(ch!=NULL, PJ_EBUG);

	ch->cseq = dlg->local.cseq++;

	 
	pjsip_tx_data_invalidate_msg( tdata );
    }

     
    if (msg->line.req.method.id != PJSIP_ACK_METHOD) {
	int tsx_count;

	status = pjsip_tsx_create_uac(dlg->ua, tdata, &tsx);
	if (status != PJ_SUCCESS)
	    goto on_error;

	 
	status = pjsip_tsx_set_transport(tsx, &dlg->tp_sel);
	pj_assert(status == PJ_SUCCESS);

	 
	tsx->mod_data[dlg->ua->id] = dlg;

	 
	if (mod_data_id >= 0 && mod_data_id < PJSIP_MAX_MODULE)
	    tsx->mod_data[mod_data_id] = mod_data;

	 
	tsx_count = ++dlg->tsx_count;

	 
	status = pjsip_tsx_send_msg(tsx, tdata);
	if (status != PJ_SUCCESS) {
	    if (dlg->tsx_count == tsx_count)
		pjsip_tsx_terminate(tsx, tsx->status_code);
	    goto on_error;
	}

    } else {
	 
	pjsip_tx_data_set_transport(tdata, &dlg->tp_sel);

	 
	status = pjsip_endpt_send_request_stateless(dlg->endpt, tdata,
						    NULL, &send_ack_callback);
	if (status != PJ_SUCCESS)
	    goto on_error;

    }

     
    pjsip_dlg_dec_lock(dlg);
    pj_log_pop_indent();
    return PJ_SUCCESS;

on_error:
     
    pjsip_dlg_dec_lock(dlg);

     
    pjsip_tx_data_dec_ref( tdata );
    pj_log_pop_indent();
    return status;
}