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 }