You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
329 lines
7.6 KiB
Go
329 lines
7.6 KiB
Go
package icssessionmanager
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"time"
|
|
|
|
"gitlab.com/ics_cinnamon/joy4/format"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icscbtimer"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icsdtmf"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icserror"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icsevent"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icslog"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icsmediaconv"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
|
|
)
|
|
|
|
type IcsSession struct {
|
|
ID int
|
|
|
|
goroutineID int
|
|
|
|
//agent config
|
|
AgentInfo *icsconf.AgentInfo
|
|
AgentConf *icsconf.AgentConfig
|
|
|
|
sipNeter *icsnet.IcsNeter
|
|
|
|
callID string
|
|
//regiCallID string
|
|
uri string //register from
|
|
srcPort int
|
|
dstPort int
|
|
direction bool
|
|
|
|
eventSystem *icsevent.EventSystem
|
|
|
|
//manage session
|
|
lastTimestamp time.Time
|
|
isStart bool
|
|
|
|
//media
|
|
invitePayloads []string
|
|
payloadType icspacketparser.PayloadType
|
|
isFoundPayload bool
|
|
TxConverter *icsmediaconv.Converter
|
|
RxConverter *icsmediaconv.Converter
|
|
txSeq int //first TX seq num
|
|
rxSeq int //first RX seq num
|
|
RTPCBStatus int
|
|
//TTS data
|
|
tts []byte
|
|
|
|
remoteSIPAddr *net.UDPAddr
|
|
|
|
//call info
|
|
StartTimeStamp int64
|
|
EndTimeStamp int64
|
|
Station string
|
|
ChannelID string
|
|
ServerID int
|
|
CustID string
|
|
|
|
/*//////////////////
|
|
rxFile *os.File
|
|
txFile *os.File
|
|
*/ //////////////////
|
|
|
|
//Voice agent conn
|
|
//CallSignalNeter icsnet.IcsNeter
|
|
VoiceNeter icsnet.IcsNeter
|
|
|
|
MethodAutomata int
|
|
|
|
//agent
|
|
AgentName string
|
|
AgentName2 string
|
|
//RTP port
|
|
RTPPort int
|
|
|
|
//register callback timer
|
|
RegisterCallBackTimer *icscbtimer.IcsCBTimer
|
|
registerStatus int
|
|
agentStatus int
|
|
//OPTIONS callback timer
|
|
OPTIONSCallBackTimer *icscbtimer.IcsCBTimer
|
|
//RTP sender callback timer
|
|
RTPSenderCallBackTimer *icscbtimer.IcsCBTimer
|
|
//INVITE callback timer
|
|
INVITECallBackTimer *icscbtimer.IcsCBTimer
|
|
|
|
//rtp/rtcp Tx/Rx neter
|
|
/*
|
|
rtpTxPort int
|
|
rtpTxIP string
|
|
rtpTxAddr *icsnet.IcsNetAddr
|
|
rtcpTxPort int
|
|
rtcpTxIP string
|
|
rtcpTxAddr *icsnet.IcsNetAddr
|
|
rtpTxNeter icsnet.IcsNeter
|
|
rtcpTxNeter icsnet.IcsNeter
|
|
*/
|
|
|
|
//remoteMediaAddr *icsnet.IcsNetAddr
|
|
rtpMediaNeter icsnet.IcsNeter
|
|
rtcpMediaNeter icsnet.IcsNeter
|
|
//media format
|
|
mediaFormat []string
|
|
//rtp info
|
|
rtpSSRC uint32
|
|
rtpSeq uint16
|
|
rtpTS uint32
|
|
|
|
//call statistic
|
|
rxCnt int
|
|
txCnt int
|
|
callStartTime time.Time
|
|
callEndTime time.Time
|
|
|
|
//cseq
|
|
Cseq uint32
|
|
RegiCseq uint32
|
|
|
|
CurrentSIP *icspacketparser.SIP
|
|
InviteSIP *icspacketparser.SIP
|
|
|
|
//dtmf handle
|
|
dtmf *icsdtmf.ICSDTMF
|
|
|
|
// botStatus
|
|
BotStatus uint32
|
|
//tmp refer to
|
|
referto string
|
|
simLoopCount int
|
|
xaiNumber string
|
|
// ExpTimer *icscbtimer.IcsCBTimer
|
|
expRead time.Time
|
|
readTimer time.Ticker
|
|
expCheck bool
|
|
mychannel chan bool
|
|
inviteDuration time.Time
|
|
TTSFlag atomic.Value
|
|
PreTTSFlag bool
|
|
silencecnt int
|
|
vaildcnt int
|
|
epd int
|
|
preepd int
|
|
|
|
m *sync.Mutex
|
|
}
|
|
|
|
type IcsSessionID int
|
|
|
|
const MAX_SESSION_IDLE = time.Hour
|
|
|
|
const (
|
|
ICS_INBOUND_CALL = true
|
|
ICS_OUTBOUND_CALL = false
|
|
)
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//session routine
|
|
|
|
//init ffmpeg
|
|
func init() {
|
|
format.RegisterAll()
|
|
}
|
|
|
|
//on/off check the session idle
|
|
func (s *IcsSession) Start() {
|
|
s.SetTimestamp(time.Now())
|
|
s.isStart = true
|
|
}
|
|
|
|
func (s *IcsSession) Stop() {
|
|
l := icslog.GetIcsLog()
|
|
l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Session Stop")
|
|
|
|
s.isStart = false
|
|
}
|
|
|
|
func (s *IcsSession) Init() *icserror.IcsError {
|
|
l := icslog.GetIcsLog()
|
|
//conf := icsconf.GetIcsConfig()
|
|
|
|
s.RTPCBStatus = 0
|
|
s.TTSFlag.Store(false)
|
|
|
|
/*
|
|
s.AgentName = s.AgentConf.Name
|
|
s.AgentName2 = fmt.Sprintf("agent%s", s.AgentConf.Name)
|
|
*/
|
|
|
|
//media format
|
|
s.mediaFormat = strings.Split(s.AgentConf.MediaConfig.Format, " ")
|
|
//s.mediaFormat = strings.Split(conf.AgentConfig[s.ID].MediaConfig.Format, " ")
|
|
//fmt.Println(len(s.mediaFormat), s.mediaFormat)
|
|
|
|
//create rx rtp/rtcp listener
|
|
s.RTPPort = s.AgentConf.MediaConfig.Port
|
|
if s.rtpMediaNeter == nil {
|
|
//s.RTPPort = conf.AgentConfig[s.ID].MediaConfig.Port
|
|
RTPAddrStr := fmt.Sprintf("0.0.0.0:%d", s.RTPPort)
|
|
RTPAddr := icsnet.NewNetAddrWithIPAddr(RTPAddrStr)
|
|
s.rtpMediaNeter = icsnet.NewUDP(&RTPAddr, nil)
|
|
RTCPAddrStr := fmt.Sprintf("0.0.0.0:%d", s.RTPPort+1)
|
|
RTCPAddr := icsnet.NewNetAddrWithIPAddr(RTCPAddrStr)
|
|
s.rtcpMediaNeter = icsnet.NewUDP(&RTCPAddr, nil)
|
|
|
|
//set rtp send callback
|
|
s.RTPPort = s.AgentConf.MediaConfig.Port
|
|
s.RTPSenderCallBackTimer = icscbtimer.NewCBTimer(time.Millisecond*20, s.SendRTPCB)
|
|
|
|
err1 := s.rtpMediaNeter.Listen()
|
|
if err1 != nil {
|
|
l.Print(icslog.LOG_LEVEL_FATAL, s.ID, err1.GetMessage())
|
|
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "%s", err1.GetError())
|
|
return err1
|
|
}
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Listening RTP port[%d]", s.RTPPort)
|
|
err1 = s.rtcpMediaNeter.Listen()
|
|
if err1 != nil {
|
|
l.Print(icslog.LOG_LEVEL_FATAL, s.ID, err1.GetMessage())
|
|
return err1
|
|
}
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Listening RTCP port[%d]", s.RTPPort+1)
|
|
|
|
s.dtmf = icsdtmf.NewICSDTMF()
|
|
|
|
go s.ReadRTP()
|
|
go s.ReadRTCP()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *IcsSession) Run() *icserror.IcsError {
|
|
mySessionID := s.GetSessionID()
|
|
l := icslog.GetIcsLog()
|
|
conf := icsconf.GetIcsConfig()
|
|
|
|
s.goroutineID = goid()
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, int(mySessionID), "Session [%d] READY\n", mySessionID)
|
|
|
|
//start callback timer func
|
|
if strings.Compare(strings.ToUpper(conf.AgentConfig[s.ID].Value), "TRUE") == 0 {
|
|
s.SetRegisterStatus(STATUS_REGISTER_READY)
|
|
s.RegisterCallBackTimer.Start()
|
|
defer s.RegisterCallBackTimer.Stop()
|
|
s.OPTIONSCallBackTimer.Start()
|
|
defer s.OPTIONSCallBackTimer.Stop()
|
|
//s.INVITECallBackTimer.Start()
|
|
//defer s.INVITECallBackTimer.Stop()
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started [%s] callback timer", conf.AgentConfig[s.ID].Name)
|
|
}
|
|
|
|
svc := icssvc.GetServiceStatus()
|
|
for !svc.GetExit() && !svc.GetStop() {
|
|
//get event
|
|
h := icsevent.NewEventH()
|
|
evt, evterr := h.GetEvent(int(mySessionID))
|
|
if evt == nil {
|
|
if evterr != nil {
|
|
//evterr.Print()
|
|
time.Sleep(time.Millisecond)
|
|
continue
|
|
}
|
|
|
|
if strings.Compare(strings.ToUpper(conf.AgentConfig[s.ID].Value), "TRUE") == 0 {
|
|
duration := time.Since(s.lastTimestamp)
|
|
if s.isStart && duration >= MAX_SESSION_IDLE {
|
|
//Session expired!
|
|
err := icserror.ICSERRSESSMaxSessionIdle
|
|
|
|
logmsg := fmt.Sprintf("Session expired. Duration: %v(%v) - %s\n", duration, s.lastTimestamp, err.GetMessage())
|
|
l.Print(icslog.LOG_LEVEL_INFO, s.ID, logmsg)
|
|
|
|
s.Stop()
|
|
serr := s.RemoveSession()
|
|
if serr != nil {
|
|
//serr.Print()
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "RemoveSession Error %s", serr.GetMessage())
|
|
}
|
|
|
|
//return err
|
|
}
|
|
}
|
|
|
|
time.Sleep(time.Millisecond)
|
|
continue
|
|
}
|
|
|
|
//refresh session timestamp
|
|
s.SetTimestamp(time.Now())
|
|
|
|
//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Get Event[%d]", evt.ID)
|
|
|
|
data := evt.GetData()
|
|
|
|
switch v := (*data).(type) {
|
|
case icspacketparser.SIP:
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Get SIP Event[%d]", evt.ID)
|
|
sip := v
|
|
s.CurrentSIP = &sip
|
|
s.Processing(&sip)
|
|
//s.analyzeSIP(&sip)
|
|
case icspacketparser.RTP:
|
|
//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Get RTP Event[%d]", evt.ID)
|
|
rtp := v
|
|
//fmt.Println(rtp)
|
|
s.analyzeRTP(&rtp)
|
|
default:
|
|
// fmt.Println(time.Now(), "NOT DEFINED EVENT TYPE!!!!!!!!!!!!!!!!!")
|
|
}
|
|
}
|
|
|
|
l.Print(icslog.LOG_LEVEL_DEBUG2, s.ID, "Stoped Session!")
|
|
|
|
return nil
|
|
}
|