Exemplo n.º 1
0
int add_cc_flow( struct cc_data *data, str *id, int priority, str *skill,
												str *cid, str *recordings )
{
	struct cc_flow *flow, *prev_flow;
	unsigned int i;
	unsigned int skill_id;
#ifdef STATISTICS
	char *name;
	str s;
#endif

	/* is the flow a new one? - search by ID */
	flow = get_flow_by_name( data, id);

	if (flow==NULL) {
		/* new flow -> create and populate one */
		flow = (struct cc_flow*)shm_malloc(sizeof(struct cc_flow)+id->len);
		if (flow==NULL) {
			LM_ERR("not enough shmem for a new flow\n");
			goto error;
		}
		memset( flow, 0, sizeof(struct cc_flow) );
		/* id */
		flow->id.s = (char*)(flow+1);
		memcpy( flow->id.s, id->s, id->len);
		flow->id.len = id->len;
		/* priority */
		flow->priority = priority;
		/* skill */
		flow->skill = get_skill_id( data, skill );
		if (flow->skill==0) {
			LM_ERR("cannot get skill id\n");
			goto error;
		}
		/* cid */
		if (cid && cid->s && cid->len) {
			flow->cid.s = (char*)shm_malloc(cid->len);
			if (flow->cid.s==NULL) {
				LM_ERR("not enough shmem for the cid of the flow\n");
				goto error;
			}
			memcpy( flow->cid.s, cid->s, cid->len);
			flow->cid.len = cid->len;
		}
		/* audio messages */
		for( i=0 ; i<MAX_AUDIO ; i++ ) {
			if (recordings[i].s && recordings[i].len) {
				flow->recordings[i].s = (char*)shm_malloc(recordings[i].len);
				if (flow->recordings[i].s==NULL) {
					LM_ERR("not enough shmem for the message %d of the flow\n",
						i);
					goto error;
				}
				memcpy( flow->recordings[i].s, recordings[i].s,
					recordings[i].len);
				flow->recordings[i].len = recordings[i].len;
			}
		}
#ifdef STATISTICS
		/* statistics */
		s.s = "ccf_incalls";s.len = 11 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &flow->st_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_dist_incalls";s.len = 15 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &flow->st_dist_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_answ_incalls";s.len = 15 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &flow->st_answ_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_aban_incalls";s.len = 15 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &flow->st_aban_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_onhold_calls";s.len = 15 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &flow->st_onhold_calls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_queued_calls";s.len = 16 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &flow->st_queued_calls, STAT_SHM_NAME|STAT_NO_RESET)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_etw";s.len = 7 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat2("call_center",
		name, (stat_var **)cc_flow_get_etw, STAT_SHM_NAME|STAT_IS_FUNC,
		(void*)flow, 0)!=0) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_awt";s.len = 7 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat2("call_center",
		name, (stat_var **)cc_flow_get_awt, STAT_SHM_NAME|STAT_IS_FUNC,
		(void*)flow, 0)!=0) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_load";s.len = 8 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat2("call_center",
		name, (stat_var **)cc_flow_get_load, STAT_SHM_NAME|STAT_IS_FUNC,
		(void*)flow, 0)!=0) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "ccf_free_agents";s.len = 15 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat2("call_center",
		name, (stat_var **)cc_flow_free_agents, STAT_SHM_NAME|STAT_IS_FUNC,
		(void*)flow, 0)!=0) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
#endif

		flow->is_new = 1;
		/* insert the new flow in the list */
		flow->next = data->flows;
		data->flows = flow;
	} else {
		/* flow already exists -> update */
		/* priority */
		flow->priority = priority;
		/* skill - needs to be changed ? */
		skill_id = get_skill_id(data,skill);
		if (skill_id==0) {
			LM_ERR("cannot get skill id\n");
			goto error1;
		}
		flow->skill = skill_id;
		/* cid - needs to be changed ? */
		if ( flow->cid.len && ( cid->len==0 ||
		cid->len>flow->cid.len || memcmp(flow->cid.s,cid->s,cid->len)!=0) ) {
			shm_free(flow->cid.s); flow->cid.s = NULL; flow->cid.len = 0 ;
		}
		if (flow->cid.s==NULL && cid->len!=0) {
			flow->cid.s = (char*)shm_malloc(cid->len);
			if (flow->cid.s==NULL) {
				LM_ERR("not enough shmem for the cid of the flow\n");
				goto error1;
			}
		}
		if (flow->cid.s) {
			memcpy( flow->cid.s, cid->s, cid->len);
			flow->cid.len = cid->len;
		}
		/* audio messages */
		for( i=0 ; i<MAX_AUDIO ; i++ ) {
			if ( flow->recordings[i].len && ( recordings[i].len==0 ||
			recordings[i].len>flow->recordings[i].len ||
			memcmp(flow->recordings[i].s,recordings[i].s,recordings[i].len)
			) ) {
				shm_free(flow->recordings[i].s); flow->recordings[i].s = NULL;
				flow->recordings[i].len = 0 ;
			}
			if (flow->recordings[i].s==NULL && recordings[i].len!=0) {
				flow->recordings[i].s = (char*)shm_malloc(recordings[i].len);
				if (flow->recordings[i].s==NULL) {
					LM_ERR("not enough shmem for the message of the flow\n");
					goto error1;
				}
			}
			if (flow->recordings[i].s) {
				memcpy( flow->recordings[i].s, recordings[i].s,
					recordings[i].len);
				flow->recordings[i].len = recordings[i].len;
			}
		}
		flow->is_new = 1;

	}

	return 0;

error1:
	if(data->flows == flow)
		data->flows = flow->next;
	else
	for(prev_flow=data->flows; prev_flow; prev_flow=prev_flow->next)
		if(prev_flow->next == flow) {
			prev_flow->next = flow->next;
			break;
		}
error:
	if (flow)
		free_cc_flow(flow);
	return -1;
}
Exemplo n.º 2
0
static int w_handle_call(struct sip_msg *msg, char *flow_var)
{
	struct cc_flow *flow;
	struct cc_call *call;
	str leg = {NULL,0};
	str *dn;
	str val;
	int dec;
	int ret = -1;

	call = NULL;
	dec = 0;

	/* get the flow name */
	if (fixup_get_svalue(msg, (gparam_p)flow_var, &val)!=0) {
		LM_ERR("failed to avaluate the flow name variable\n");
		return -1;
	}

	/* parse FROM URI */
	if (parse_from_uri(msg)==NULL) {
		LM_ERR("failed to parse from hdr\n");
		return -2;
	}

	lock_get( data->lock );

	/* get the flow ID */
	flow = get_flow_by_name(data, &val);
	if (flow==NULL) {
		LM_ERR("flow <%.*s> does not exists\n", val.len, val.s);
		ret = -3;
		goto error;
	}
	LM_DBG("using call flow %p\n", flow);

	if (flow->logged_agents==0 /* no logged agents */ ) {
		LM_NOTICE("flow <%.*s> closed\n",flow->id.len,flow->id.s);
		ret = -4;
		goto error;
	}

	update_stat(stg_incalls, 1);
	update_stat(flow->st_incalls, 1);

	if (flow->cid.len) {
		dn = build_displayname(&flow->cid, get_from(msg));
	} else if (get_from(msg)->display.len) {
		dn = &get_from(msg)->display;
	} else {
		dn = &get_from(msg)->parsed_uri.user;
	}
	LM_DBG("cid=<%.*s>\n",dn->len,dn->s);

	call = new_cc_call(data, flow, dn, &get_from(msg)->parsed_uri.user);
	if (call==NULL) {
		LM_ERR("failed to create new call\n");
		ret = -5;
		goto error;
	}
	call->fst_flags |= FSTAT_INCALL;

	/* get estimated wait time */
	call->eta = (unsigned int) (( flow->avg_call_duration *
		(float)get_stat_val(flow->st_queued_calls) ) /
		(float)flow->logged_agents);
	
	LM_DBG("avg_call_duration=%.2f queued_calls=%lu logedin_agents=%u\n",
		flow->avg_call_duration, get_stat_val(flow->st_queued_calls),
		flow->logged_agents);

	LM_DBG("ETA for new call(%p) is %d\n", call, call->eta);

	/* one more call to process */
	flow->ongoing_calls++;

	/* there is no need to lock the call here as it is not 
	 * yet sharead at all - just we have a ref to it */
	
	/* get the first state */
	if (cc_call_state_machine( data, call, &leg )!=0) {
		LM_ERR("failed to get first call destination \n");
		ret = -5;
		goto error;
	}

	lock_release( data->lock );
	LM_DBG("new destination for call(%p) is %.*s (state=%d)\n",
		call, leg.len, leg.s, call->state);

	/* call still waits for agent ? */
	if (call->state!=CC_CALL_TOAGENT) {
		LM_DBG("** onhold++ Not to agent [%p]\n", call);
		update_stat( stg_onhold_calls, +1);
		update_stat( flow->st_onhold_calls, +1);
		dec = 1;
	}

	/* send call to selected destination */
	if (set_call_leg( msg, call, &leg)< 0 ) {
		LM_ERR("failed to set new destination for call\n");
		if (dec) { 
			LM_DBG("** onhold-- Error [%p]\n", call);
			update_stat( stg_onhold_calls, -1);
			update_stat( flow->st_onhold_calls, -1);
		}
		pkg_free(leg.s);
		goto error1;
	}

	pkg_free(leg.s);

	if(cc_db_insert_call(call) < 0) {
		LM_ERR("Failed to insert call record in db\n");
	}

	return 1;
error:
	lock_release( data->lock );
error1:
	if (call) { free_cc_call( data, call); flow->ongoing_calls--; }
	return ret;
}