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; }
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; }