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.

319 lines
7.3 KiB
Go

package icssessionmanager
import (
"fmt"
"strings"
"sync"
"time"
"net"
"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
// ExpTimer *icscbtimer.IcsCBTimer
expRead time.Time
readTimer time.Ticker
expCheck bool
mychannel chan bool
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.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
}