Ejemplo n.º 1
0
void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
	//int i;
	int unref = 0;
	struct ro_session *ro_session = 0;
	struct ro_session_entry *ro_session_entry;
	struct sip_msg *request;
	
	LM_DBG("dialog [%p] terminated, lets send stop record\n", dlg);

	if (!_params) {
		return;
	}
	
	ro_session = (struct ro_session*)*_params->param;
	if (!ro_session) {
		LM_ERR("Ro Session object is NULL...... aborting\n");
		return;
	}
	
	request = _params->req;
	if (!request) {
		LM_WARN("dlg_terminated has no SIP request associated.\n");
	}

	if (dlg && (dlg->callid.s && dlg->callid.len > 0)) {
		
	    
	    /* find the session for this call, possibly both for orig and term*/
		//for (i=0; i<2; i++) {
			//TODO: try and get the Ro session specifically for terminating dialog or originating one
			//currently the way we are doing is a hack.....
			//if ((ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
				ro_session_entry =
						&(ro_session_table->entries[ro_session->h_entry]);

				//if the Ro session is not active we don't need to do anything. This prevents
				//double processing for various dialog_terminated callback events.
				//If however, the call was never answered, then we can continue as normal
				if (!ro_session->active && (ro_session->start_time != 0)) {
					unref_ro_session(ro_session,1);
					LM_ERR("Ro Session is not active, but may have been answered [%d]\n", (int)ro_session->start_time);
					return;
				}
			
	
				ro_session_lock(ro_session_table, ro_session_entry);

				if (ro_session->active) { // if the call was never activated, there's no timer to remove
					int ret = remove_ro_timer(&ro_session->ro_tl);
					if (ret < 0) {
						LM_CRIT("unable to unlink the timer on ro_session %p [%.*s]\n", 
							ro_session, ro_session->cdp_session_id.len, ro_session->cdp_session_id.s);
					} else if (ret > 0) {
						LM_WARN("inconsistent ro timer data on ro_session %p [%.*s]\n",
							ro_session, ro_session->cdp_session_id.len, ro_session->cdp_session_id.s);						
					} else {
						unref++;
					}
				}

				LM_DBG("Sending CCR STOP on Ro_Session [%p]\n", ro_session);
				send_ccr_stop(ro_session);
				ro_session->active = 0;
				//ro_session->start_time;
				unref_ro_session_unsafe(ro_session, 1+unref, ro_session_entry); //lock already acquired
				//unref_ro_session_unsafe(ro_session, 2+unref, ro_session_entry); //lock already acquired
				ro_session_unlock(ro_session_table, ro_session_entry);
			//}
		//}
	}
}
Ejemplo n.º 2
0
void dlg_terminated(struct dlg_cell *dlg, int type, unsigned int termcode, char* reason, struct dlg_cb_params *_params) {
	//int i;
	int unref = 0;
	struct ro_session *ro_session = 0;
	struct ro_session_entry *ro_session_entry;
	struct sip_msg *request;
        str s_reason;
        
        s_reason.s = reason;
        s_reason.len = strlen(reason);
	
	LM_DBG("dialog [%p] terminated on type [%d], lets send stop record\n", dlg, type);

	if (!_params) {
		return;
	}
	
	LM_DBG("Direction is %d\n", _params->direction);
	if (_params->req) {
		if (_params->req->first_line.u.request.method_value == METHOD_BYE) {
			if (_params->direction == DLG_DIR_DOWNSTREAM) {
				LM_DBG("Dialog ended by Caller\n");
			} else {
				LM_DBG("Dialog ended by Callee\n");
			}
		} else {
			LM_DBG("Request is %.*s\n", _params->req->first_line.u.request.method.len, _params->req->first_line.u.request.method.s);
		}

		struct hdr_field* h = get_hdr_by_name(_params->req, "Reason", 6);
		if(h!=NULL){
                        LM_DBG("reason header is [%.*s]\n", h->body.len, h->body.s);
			s_reason = h->body;
		}
	} else if (_params->rpl) {
		LM_DBG("Reply is [%d - %.*s]", _params->rpl->first_line.u.reply.statuscode, _params->rpl->first_line.u.reply.reason.len, _params->rpl->first_line.u.reply.reason.s);
	}
	
	ro_session = (struct ro_session*)*_params->param;
	if (!ro_session) {
		LM_ERR("Ro Session object is NULL...... aborting\n");
		return;
	}
	
	request = _params->req;
	if (!request) {
		LM_WARN("dlg_terminated has no SIP request associated.\n");
	}

	if (dlg && (dlg->callid.s && dlg->callid.len > 0)) {
		
	    
	    /* find the session for this call, possibly both for orig and term*/
		//for (i=0; i<2; i++) {
			//TODO: try and get the Ro session specifically for terminating dialog or originating one
			//currently the way we are doing is a hack.....
			//if ((ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
				ro_session_entry =
						&(ro_session_table->entries[ro_session->h_entry]);

				//if the Ro session is not active we don't need to do anything. This prevents
				//double processing for various dialog_terminated callback events.
				//If however, the call was never answered, then we can continue as normal
				ro_session_lock(ro_session_table, ro_session_entry);
                                
                                LM_DBG("processing dlg_terminated in Ro and session [%.*s] has active = %d", ro_session->ro_session_id.len, ro_session->ro_session_id.s, ro_session->active);
				if ((!ro_session->active && (ro_session->start_time != 0)) || (ro_session->ccr_sent == 1)) {
					unref_ro_session_unsafe(ro_session,1,ro_session_entry);
					LM_DBG("CCR already sent or Ro Session is not active, but may have been answered [%d]\n", (int)ro_session->start_time);
					ro_session_unlock(ro_session_table, ro_session_entry);
					return;
				}

				if (ro_session->active) { // if the call was never activated, there's no timer to remove
					int ret = remove_ro_timer(&ro_session->ro_tl);
					if (ret < 0) {
						LM_CRIT("unable to unlink the timer on ro_session %p [%.*s]\n", 
							ro_session, ro_session->ro_session_id.len, ro_session->ro_session_id.s);
					} else if (ret > 0) {
						LM_WARN("inconsistent ro timer data on ro_session %p [%.*s]\n",
							ro_session, ro_session->ro_session_id.len, ro_session->ro_session_id.s);						
					} else {
						unref++;
					}
				}

				LM_DBG("Sending CCR STOP on Ro_Session [%p]\n", ro_session);
				send_ccr_stop_with_param(ro_session, termcode, &s_reason);
				ro_session->active = -1;    //deleted.... terminated ....
                                ro_session->ccr_sent = 1;
//                                counter_add(ims_charging_cnts_h.active_ro_sessions, -1);
				
				if (ro_db_mode == DB_MODE_REALTIME) {
				    ro_session->flags |= RO_SESSION_FLAG_DELETED;
				    if (update_ro_dbinfo_unsafe(ro_session) != 0) {
					LM_ERR("Unable to update Ro session in DB...continuing\n");
				    }
				}
				
				//ro_session->start_time;
				unref_ro_session_unsafe(ro_session, 1+unref, ro_session_entry); //lock already acquired
				//unref_ro_session_unsafe(ro_session, 2+unref, ro_session_entry); //lock already acquired
				ro_session_unlock(ro_session_table, ro_session_entry);
			//}
		//}
	}
}