Пример #1
0
int add_cc_agent( struct cc_data *data, str *id, str *location,
				str *skills, unsigned int logstate, unsigned int last_call_end)
{
	struct cc_agent *agent, *prev_agent= 0;
	struct sip_uri uri;
	str skill;
	char *p;
	unsigned int n,skill_id;
#ifdef STATISTICS
	char *name;
	str s;
#endif

	/* is the agent a new one? - search by ID */
	agent = get_agent_by_name( data, id, &prev_agent);

	if (agent==NULL) {
		/* new agent -> create and populate one */
		agent = (struct cc_agent*)shm_malloc(sizeof(struct cc_agent)+id->len);
		if (agent==NULL) {
			LM_ERR("not enough shmem for a new agent\n");
			goto error;
		}
		memset( agent, 0, sizeof(struct cc_agent) );
		/* id */
		agent->id.s = (char*)(agent+1);
		memcpy( agent->id.s, id->s, id->len);
		agent->id.len = id->len;
		/* location */
		agent->location.s = (char*)shm_malloc(location->len);
		if (agent->location.s==NULL) {
			LM_ERR("not enough shmem for the location of the agent\n");
			goto error;
		}
		memcpy( agent->location.s, location->s, location->len);
		agent->location.len = location->len;
		if (parse_uri( agent->location.s, agent->location.len, &uri)<0) {
			LM_ERR("location of the agent is not a SIP URI\n");
			goto error;
		}
		agent->did = uri.user;
		/* LOG STATE */
		agent->loged_in = logstate;
		/* set of skills */
		if (skills && skills->len) {
			p = skills->s;
			while (p) {
				skill.s = p;
				p = q_memchr(skill.s, ',', skills->s+skills->len-skill.s);
				skill.len = p?(p-skill.s):(skills->s+skills->len-skill.s);
				trim(&skill);
				if (skill.len) {
					skill_id = get_skill_id(data,&skill);
					if (skill_id==0) {
						LM_ERR("cannot get skill id\n");
						goto error;
					}
					n = agent->no_skills++; 
					agent->skills[n] = skill_id;
				}
				if(p)
					p++;
			}
		}
		/* statistics */
#ifdef STATISTICS
		s.s = "cca_dist_incalls";s.len = 16 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &agent->st_dist_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "cca_answ_incalls";s.len = 16 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &agent->st_answ_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "cca_aban_incalls";s.len = 16 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center",
		name, &agent->st_aban_incalls, STAT_SHM_NAME)!=0 ) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
		s.s = "cca_att";s.len = 7 ;
		if ( (name=build_stat_name( &s, id->s))==0 || register_stat2("call_center",
		name, (stat_var **)cc_agent_get_att, STAT_SHM_NAME|STAT_IS_FUNC,
		(void*)agent, 0)!=0) {
			LM_ERR("failed to add stat variable\n");
			goto error;
		}
#endif
		if(last_call_end && (last_call_end + wrapup_time < (int)time(NULL))) {
			agent->state = CC_AGENT_WRAPUP;
			agent->last_call_end = last_call_end - startup_time; /* it will be a negative value */
		}
		agent->is_new = 1;
		/* link the agent */
		add_cc_agent_top(data, agent);
		data->totalnr_agents++;
	} else {
		/* agent already exists -> update only */
		/* location - needs to be changed ? */
		if ( agent->location.len!=location->len ||
			memcmp(agent->location.s,location->s,location->len)!=0 ) {
			/* set new location */
			if (agent->location.len < location->len ){
				shm_free(agent->location.s);
				agent->location.s = (char*)shm_malloc(location->len);
				if (agent->location.s==NULL) {
					LM_ERR("not enough shmem for the location of the agent\n");
					goto error1;
				}
			}
			memcpy( agent->location.s, location->s, location->len);
			agent->location.len = location->len;
			if (parse_uri( agent->location.s, agent->location.len, &uri)<0) {
				LM_ERR("location of the agent is not a SIP URI\n");
				goto error1;
			}
			agent->did = uri.user;
		}
		/* if logstate changed - move between the lists TODO */
		if(logstate != agent->loged_in) {
			agent_switch_login(data, agent, prev_agent);
		}
		/* skills - needs to be changed ? */
		agent->no_skills = 0;
		if (skills && skills->len) {
			p = skills->s;
			while (p) {
				skill.s = p;
				p = q_memchr(skill.s, ',', skills->s+skills->len-skill.s);
				skill.len = p?(p-skill.s):(skills->s+skills->len-skill.s);
				trim(&skill);
				if (skill.len) {
					skill_id = get_skill_id(data,&skill);
					if (skill_id==0) {
						LM_ERR("cannot get skill id\n");
						goto error1;
					}
					n = agent->no_skills++; 
					agent->skills[n] = skill_id;
				}
				if(p)
					p++;
			}
		}
		agent->is_new = 1;
	}

	return 0;
error1:
	remove_cc_agent(data, agent, prev_agent);
error:
	if (agent)
		free_cc_agent(agent);
	return 0;
}
Пример #2
0
static void cc_timer_agents(unsigned int ticks, void* param)
{
	struct cc_agent *agent, *prev_agent, *tmp_ag;
	struct cc_call  *call;
	str out;
	str dest;

	if (data==NULL || data->agents[CC_AG_ONLINE]==NULL)
		return;

	do {

		lock_get( data->lock );

		prev_agent = data->agents[CC_AG_ONLINE];
		agent = data->agents[CC_AG_ONLINE];
		call = NULL;

		/* iterate all agents*/
		do {

			//LM_DBG("%.*s , state=%d, last_call_end=%u, ticks=%u, wrapup=%u\n",
			//		agent->id.len, agent->id.s, agent->state, agent->last_call_end, ticks, wrapup_time);
			/* for agents in WRAPUP time, check if expired */
			if ( (agent->state==CC_AGENT_WRAPUP) &&
					(ticks - agent->last_call_end > wrapup_time)) {
				agent->state = CC_AGENT_FREE;
				/* move it to the end of the list*/
				if(data->last_online_agent != agent) {
					remove_cc_agent(data, agent, prev_agent);
					if(!data->last_online_agent) {
						LM_CRIT("last_online_agent NULL\n");
						if(data->agents[CC_AG_ONLINE] == NULL)
							data->agents[CC_AG_ONLINE] = agent;
						else {
							for (tmp_ag = data->agents[CC_AG_ONLINE]; tmp_ag; tmp_ag= tmp_ag->next)
							{
								prev_agent = tmp_ag;
							}
							prev_agent->next = agent;
							agent->next = NULL;
							data->last_online_agent = agent;
						}
					}
					else {
							data->last_online_agent->next = agent;
							agent->next = NULL;
							data->last_online_agent = agent;
					}
					goto next_ag;
				}
			}

			/* for free agents -> check for calls */
			if ( (data->queue.calls_no!=0) && (agent->state==CC_AGENT_FREE) ) {
				call = cc_queue_pop_call_for_agent( data, agent);
				if (call) {
					/* found a call for the agent */
					break;
				}
			}
next_ag:
			/* next agent */
			prev_agent = agent;
			agent = agent->next;

		}while(agent);

		lock_release( data->lock );

		/* no locking here */

		if (call) {

			lock_get( call->lock );
			call->ref_cnt--;

			/* is the call state still valid? (as queued) */
			if(call->state != CC_CALL_QUEUED) {
				if (call->state==CC_CALL_ENDED && call->ref_cnt==0) {
					lock_release( call->lock );
					free_cc_call( data, call);
				} else {
					lock_release( call->lock );
				}
				continue;
			}
			LM_DBG("Call %p ref= %d, state= %d\n", call,
					call->ref_cnt, call->state);

			lock_get( data->lock );

			dest = agent->location;

			/* make a copy for destination to agent */
			out.len = OUT_BUF_LEN(dest.len);
			out.s = out_buf;
			memcpy( out.s, dest.s, out.len);
			
			call->prev_state = call->state;
			call->state = CC_CALL_TOAGENT;
			/* call no longer on wait */
			LM_DBG("** onhold-- Took out of the queue [%p]\n", call);
			update_stat( stg_onhold_calls, -1);
			update_stat( call->flow->st_onhold_calls, -1);

			/* mark agent as used */
			agent->state = CC_AGENT_INCALL;
			call->agent = agent;
			call->agent->ref_cnt++;
			update_stat( stg_dist_incalls, 1);
			update_stat( call->flow->st_dist_incalls, 1);
			call->fst_flags |= FSTAT_DIST;
			update_stat( call->agent->st_dist_incalls, +1);

			/* unlock data */
			lock_release( data->lock );

			/* send call to selected agent */
			if (set_call_leg( NULL, call, &out)< 0 ) {
				LM_ERR("failed to set new destination for call\n");
			}
			lock_release( call->lock );

			if(cc_db_update_call(call) < 0)
			{
				LM_ERR("Failed to update call in database\n");
			}
		}

	} while (call);
}