Exemple #1
0
/*
map[secure: hostname:CgrDev1 callstate:ACTIVE callee_num:1002 initial_dest:1002 state:CS_EXECUTE dialplan:XML read_codec:SPEEX initial_ip_addr:127.0.0.1 write_codec:SPEEX write_bit_rate:44000
call_uuid:3427e500-10e5-4864-a589-e306b70419a2 presence_id: initial_cid_name:1001 context:default read_rate:32000 read_bit_rate:44000 callee_direction:SEND initial_context:default created:2015-06-15 18:48:13
dest:1002 callee_name:Outbound Call direction:inbound ip_addr:127.0.0.1 sent_callee_name:Outbound Call write_rate:32000 presence_data: sent_callee_num:1002 created_epoch:1434386893 cid_name:1001 application:sched_hangup
application_data:+10800 alloted_timeout uuid:3427e500-10e5-4864-a589-e306b70419a2 name:sofia/cgrtest/[email protected] cid_num:1001 initial_cid_num:1001 initial_dialplan:XML]
*/
func (sm *FSSessionManager) SyncSessions() error {
	for connId, senderPool := range sm.senderPools {
		var aChans []map[string]string
		fsConn, err := senderPool.PopFSock()
		if err != nil {
			if err == fsock.ErrConnectionPoolTimeout { // Timeout waiting for connections to re-establish, cleanup calls
				aChans = make([]map[string]string, 0) // Emulate no call information so we can disconnect bellow
			} else {
				utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Error on syncing active calls, senderPool: %+v, error: %s", senderPool, err.Error()))
				continue
			}
		} else {
			activeChanStr, err := fsConn.SendApiCmd("show channels")
			senderPool.PushFSock(fsConn)
			if err != nil {
				utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Error on syncing active calls, senderPool: %+v, error: %s", senderPool, err.Error()))
				continue
			}
			aChans = fsock.MapChanData(activeChanStr)
			if len(aChans) == 0 && strings.HasPrefix(activeChanStr, "uuid,direction") { // Failed converting output from FS
				utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Syncing active calls, failed converting output from FS: %s", activeChanStr))
				continue
			}
		}
		for _, session := range sm.sessions.getSessions() {
			if session.connId != connId { // This session belongs to another connectionId
				continue
			}
			var stillActive bool
			for _, fsAChan := range aChans {
				if fsAChan["call_uuid"] == session.eventStart.GetUUID() || (fsAChan["call_uuid"] == "" && fsAChan["uuid"] == session.eventStart.GetUUID()) { // Channel still active
					stillActive = true
					break
				}
			}
			if stillActive { // No need to do anything since the channel is still there
				continue
			}
			utils.Logger.Warning(fmt.Sprintf("<SM-FreeSWITCH> Sync active channels, stale session detected, uuid: %s", session.eventStart.GetUUID()))
			fsev := session.eventStart.(FSEvent)
			now := time.Now()
			aTime, _ := fsev.GetAnswerTime("", sm.timezone)
			dur := now.Sub(aTime)
			fsev[END_TIME] = now.String()
			fsev[DURATION] = strconv.FormatFloat(dur.Seconds(), 'f', -1, 64)
			if err := sm.sessions.removeSession(session, fsev); err != nil { // Stop loop, refund advanced charges and save the costs deducted so far to database
				utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Error on removing stale session with uuid: %s, error: %s", session.eventStart.GetUUID(), err.Error()))
				continue
			}
		}
	}
	return nil
}
/*
map[secure: hostname:CgrDev1 callstate:ACTIVE callee_num:1002 initial_dest:1002 state:CS_EXECUTE dialplan:XML read_codec:SPEEX initial_ip_addr:127.0.0.1 write_codec:SPEEX write_bit_rate:44000
call_uuid:3427e500-10e5-4864-a589-e306b70419a2 presence_id: initial_cid_name:1001 context:default read_rate:32000 read_bit_rate:44000 callee_direction:SEND initial_context:default created:2015-06-15 18:48:13
dest:1002 callee_name:Outbound Call direction:inbound ip_addr:127.0.0.1 sent_callee_name:Outbound Call write_rate:32000 presence_data: sent_callee_num:1002 created_epoch:1434386893 cid_name:1001 application:sched_hangup
application_data:+10800 alloted_timeout uuid:3427e500-10e5-4864-a589-e306b70419a2 name:sofia/cgrtest/[email protected] cid_num:1001 initial_cid_num:1001 initial_dialplan:XML]
*/
func (sm *FSSessionManager) SyncSessions() error {
	for connId, senderPool := range sm.senderPools {
		fsConn, err := senderPool.PopFSock()
		if err != nil {
			utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Error on syncing active calls, senderPool: %+v, error: %s", senderPool, err.Error()))
			continue
		}
		activeChanStr, err := fsConn.SendApiCmd("show channels")
		senderPool.PushFSock(fsConn)
		if err != nil {
			utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Error on syncing active calls, senderPool: %+v, error: %s", senderPool, err.Error()))
			continue
		}
		aChans := fsock.MapChanData(activeChanStr)
		for _, session := range sm.sessions {
			if session.connId != connId { // This session belongs to another connectionId
				continue
			}
			var stillActive bool
			for _, fsAChan := range aChans {
				if fsAChan["call_uuid"] == session.eventStart.GetUUID() { // Channel still active
					stillActive = true
					break
				}
			}
			if stillActive { // No need to do anything since the channel is still there
				continue
			}
			utils.Logger.Warning(fmt.Sprintf("<SM-FreeSWITCH> Sync active channels, stale session detected, uuid: %s", session.eventStart.GetUUID()))
			sm.RemoveSession(session.eventStart.GetUUID()) // Unreference it early so we avoid concurrency
			fsev := session.eventStart.(FSEvent)
			now := time.Now()
			aTime, _ := fsev.GetAnswerTime("", sm.timezone)
			dur := now.Sub(aTime)
			fsev[END_TIME] = now.String()
			fsev[DURATION] = strconv.FormatFloat(dur.Seconds(), 'f', -1, 64)
			if err := session.Close(fsev); err != nil { // Stop loop, refund advanced charges and save the costs deducted so far to database
				utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Error on removing stale session with uuid: %s, error: %s", session.eventStart.GetUUID(), err.Error()))
				continue
			}
		}
	}
	return nil
}