Пример #1
0
void dlg_th_up_onreply(struct cell* t, int type, struct tmcb_params *param)
{
	struct dlg_cell *dlg;

	dlg = (struct dlg_cell *)(*param->param);
	if (dlg==0)
		return;

	if(dlg_th_onreply(dlg, param->rpl, param->req, 0, DLG_DIR_UPSTREAM) < 0)
		LM_ERR("Failed to transform the reply for topology hiding\n");
}
Пример #2
0
static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
{
	struct sip_msg *rpl,*req;
	struct dlg_cell *dlg;
	int new_state;
	int old_state;
	int unref;
	int event;
	str mangled_from = {0,0};
	str mangled_to = {0,0};
	str *req_out_buff;

	dlg = (struct dlg_cell *)(*param->param);
	if (shutdown_done || dlg==0)
		return;

	rpl = param->rpl;
	req = param->req;

	if (type==TMCB_RESPONSE_FWDED) {
		/* this callback is under transaction lock (by TM), so it is save
		   to operate at write level, but we need to take care on write-read
		   conflicts -bogdan */
		if (rpl!=FAKED_REPLY) {
			if (req->msg_flags & (FL_USE_UAC_FROM | FL_USE_UAC_TO ) ) {
				req_out_buff = &t->uac[d_tmb.get_branch_index()].request.buffer;
				if (extract_ftc_hdrs(req_out_buff->s,req_out_buff->len,
				(req->msg_flags & FL_USE_UAC_FROM )?&mangled_from:0,
				(req->msg_flags & FL_USE_UAC_TO )?&mangled_to:0,0,0) != 0) {
					LM_ERR("failed to extract mangled FROM and TO hdrs\n");
					mangled_from.len = 0;
					mangled_from.s = NULL;
					mangled_to.len = 0;
					mangled_to.s = NULL;
				} else {
					if ((req->msg_flags & FL_USE_UAC_FROM) && (mangled_from.len == 0 || mangled_from.s == NULL))
						LM_CRIT("extract_ftc_hdrs ok but no from extracted : [%.*s]\n",req_out_buff->len,req_out_buff->s);

					if ((req->msg_flags & FL_USE_UAC_TO) && (mangled_to.len == 0 || mangled_to.s == NULL))
						LM_CRIT("extract_ftc_hdrs ok but no to extracted : [%.*s]\n",req_out_buff->len,req_out_buff->s);
				}
			}
			push_reply_in_dialog( rpl, t, dlg,&mangled_from,&mangled_to);
			if((dlg->flags & DLG_FLAG_TOPHIDING) && 
					dlg_th_onreply(dlg, rpl,req, 1, DLG_DIR_UPSTREAM) < 0)
				LM_ERR("Failed to transform the reply for topology hiding\n");
		} else {
			LM_DBG("dialog replied from script - cannot get callee info\n");
		}
		/* The state does not change, but the msg is mutable in this callback*/
		run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
		return;
	}
	if (type==TMCB_TRANS_CANCELLED) {
		/* only if we did force match the Cancel to the
		 * dialog before ( from the script ) */
		if (current_dlg_pointer == NULL) {
			/* reference and attached to script */
			ref_dlg(dlg,1);
			current_dlg_pointer = t->dialog_ctx;
		}
		return;
	}

	if (type==TMCB_TRANS_DELETED)
		event = DLG_EVENT_TDEL;
	else if (param->code<200)
		event = DLG_EVENT_RPL1xx;
	else if (param->code<300)
		event = DLG_EVENT_RPL2xx;
	else
		event = DLG_EVENT_RPL3xx;

	next_state_dlg( dlg, event, &old_state, &new_state, &unref);

	if (new_state==DLG_STATE_EARLY && old_state!=DLG_STATE_EARLY) {
		run_dlg_callbacks(DLGCB_EARLY, dlg, rpl, DLG_DIR_UPSTREAM, 0);
	        if_update_stat(dlg_enable_stats, early_dlgs, 1);
		return;
	}

	if (new_state==DLG_STATE_CONFIRMED_NA &&
	old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
		LM_DBG("dialog %p confirmed\n",dlg);

		/* set start time */
		dlg->start_ts = (unsigned int)(time(0));

		if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
			LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
				dlg->callid.len, dlg->callid.s,
				dlg->legs[DLG_CALLER_LEG].tag.len,
				dlg->legs[DLG_CALLER_LEG].tag.s,
				dlg->legs[callee_idx(dlg)].tag.len,
				ZSW(dlg->legs[callee_idx(dlg)].tag.s));
		} else {
			/* reference dialog as kept in timer list */
			ref_dlg(dlg,1);
		}

		if (dlg->flags & DLG_FLAG_PING_CALLER || dlg->flags & DLG_FLAG_PING_CALLEE) {
			if (0 != insert_ping_timer( dlg)) {
				LM_CRIT("Unable to insert ping dlg %p [%u:%u] on event %d [%d->%d] "
					"with clid '%.*s' and tags '%.*s' '%.*s'\n",
					dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
					dlg->callid.len, dlg->callid.s,
					dlg->legs[DLG_CALLER_LEG].tag.len,
					dlg->legs[DLG_CALLER_LEG].tag.s,
					dlg->legs[callee_idx(dlg)].tag.len,
					ZSW(dlg->legs[callee_idx(dlg)].tag.s));
			} else {
				/* reference dialog as kept in ping timer list */
				ref_dlg(dlg,1);
			}
		}

		/* save the settings to the database, 
		 * if realtime saving mode configured- save dialog now
		 * else: the next time the timer will fire the update*/
		dlg->flags |= DLG_FLAG_NEW;
		if ( dlg_db_mode==DB_MODE_REALTIME )
			update_dialog_dbinfo(dlg);

		/* dialog confirmed */
		run_dlg_callbacks( DLGCB_CONFIRMED, dlg, rpl, DLG_DIR_UPSTREAM, 0);

		if (replication_dests)
			replicate_dialog_created(dlg);

		if (old_state==DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, -1);

		if_update_stat(dlg_enable_stats, active_dlgs, 1);
		return;
	}

	if ( old_state!=DLG_STATE_DELETED && new_state==DLG_STATE_DELETED ) {
		LM_DBG("dialog %p failed (negative reply)\n", dlg);

		/*destroy linkers */
		destroy_linkers(dlg->profile_links);
		dlg->profile_links = NULL;

		/* dialog setup not completed (3456XX) */
		run_dlg_callbacks( DLGCB_FAILED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
		/* do unref */
		if (unref)
			unref_dlg(dlg,unref);
		if (old_state==DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, -1);
		if_update_stat(dlg_enable_stats, failed_dlgs, 1);
		return;
	}

	/* in any other case, check if the dialog state machine
	   requests to unref the dialog */
	if (unref)
		unref_dlg(dlg,unref);

	return;
}