package icssessionmanager import ( "bytes" "encoding/binary" "fmt" "io" "strings" "sync" "time" // "strconv" "gitlab.com/ics_cinnamon/voicegateway/icscbtimer" "gitlab.com/ics_cinnamon/voicegateway/icsconf" "gitlab.com/ics_cinnamon/voicegateway/icserror" "gitlab.com/ics_cinnamon/voicegateway/icsevent" "gitlab.com/ics_cinnamon/voicegateway/icslog" "gitlab.com/ics_cinnamon/voicegateway/icsnet" "gitlab.com/ics_cinnamon/voicegateway/icspacketparser" "gitlab.com/ics_cinnamon/voicegateway/icssvc" "gitlab.com/ics_cinnamon/voicegateway/recorddata" "gitlab.com/ics_cinnamon/voicegateway/sipasm" ) type SessionManager struct { evtSystem []*icsevent.EventSystem sessions []*IcsSession event *icsevent.EventH //sip listener SIPNeter icsnet.IcsNeter //bot-command net CommNet *icsnet.IcsTCPNet } var bigSession []*IcsSession //var bigSession []*IcsSession var onceSession sync.Once var channelNum int func getSessionInstance(SIPNeter *icsnet.IcsNeter) []*IcsSession { //l := icslog.GetIcsLog() onceSession.Do(func() { bigSession = make([]*IcsSession, channelNum) svc := icssvc.GetServiceStatus() conf := svc.GetIcsConfig() agentNum := len(conf.AgentConfig) for iter := 0; iter < channelNum; iter++ { bigSession[iter] = new(IcsSession) bigSession[iter].m = &sync.Mutex{} bigSession[iter].ID = iter //bigSession[iter].goroutineID = goid() bigSession[iter].isStart = false //bigSession[iter].lastTimestamp = time.Now() bigSession[iter].Cseq = 0 bigSession[iter].registerStatus = STATUS_REGISTER_NOT_READY bigSession[iter].agentStatus = STATUS_AGENT_NOT_READY bigSession[iter].AgentName = conf.AgentConfig[iter].Name bigSession[iter].simLoopCount = 1 bigSession[iter].AgentName2 = fmt.Sprintf("agent%s", conf.AgentConfig[iter].Name) if iter < agentNum { if strings.Contains(strings.ToUpper(conf.AgentConfig[iter].Value), "TRUE") { /* //set rtp send callback bigSession[iter].RTPPort = conf.AgentConfig[iter].MediaConfig.Port bigSession[iter].RTPSenderCallBackTimer = icscbtimer.NewCBTimer( time.Millisecond*20, bigSession[iter].SendRTPCB) //set session's agentInfo conf agentInfo := bigSession[iter].FindAgentInfo(bigSession[iter].AgentName) if agentInfo != nil { bigSession[iter].SetAgentInfo(agentInfo) } */ } else { bigSession[iter].RTPPort = -1 } //set register callback timer if strings.Contains(strings.ToUpper(conf.AgentConfig[iter].RegisterConfig.RegisterValue), "TRUE") { //bigSession[iter].RegisterCallBackTimer = icscbtimer.NewCBTimer(time.Millisecond*100, bigSession[iter].RequestRegisterCB) regiExpire := conf.AgentConfig[iter].RegisterConfig.RegisterExpire bigSession[iter].RegisterCallBackTimer = icscbtimer.NewCBTimer( time.Millisecond*1000*time.Duration(regiExpire), bigSession[iter].RequestRegisterCB) } else { bigSession[iter].registerStatus = STATUS_REGISTER_REGISTERED bigSession[iter].agentStatus = STATUS_AGENT_READY bigSession[iter].MethodAutomata = 32767 } //set options callback timer if strings.Contains(strings.ToUpper(conf.AgentConfig[iter].OptionsConfig.OptionsValue), "TRUE") { interval := conf.AgentConfig[iter].OptionsConfig.OptionsInterval bigSession[iter].OPTIONSCallBackTimer = icscbtimer.NewCBTimer( time.Millisecond*1000*time.Duration(interval), bigSession[iter].RequestOptionsCB) } /* //set invite callback timer bigSession[iter].INVITECallBackTimer = icscbtimer.NewCBTimer( time.Millisecond*1000*time.Duration(1), bigSession[iter].RequestInviteCB) if err := bigSession[iter].Init(); err != nil { l.Printf(icslog.LOG_LEVEL_FATAL, -1, "Session Init error. Voice Agent EXIT!! - %s", err.GetMessage()) os.Exit(0) } */ } bigSession[iter].eventSystem = icsevent.GetMyEventSystem(iter) //bigSession[iter].Init(iter) //set sip connection to each sessions bigSession[iter].sipNeter = SIPNeter } }) return bigSession } //TODO: make this function to singleton func NewSessionManager() *SessionManager { l := icslog.GetIcsLog() conf := icsconf.GetIcsConfig() svc := icssvc.NewService() channelNum = svc.GetIcsConfig().GetChannelNum() //icsevent.SetConfig(svc.GetIcsConfig()) sm := new(SessionManager) icsevent.SetChannelNum(channelNum) sm.evtSystem = icsevent.GetEvtSystemInstance() //start sip listen sipPort := conf.SIPConfig.Port transport := conf.SIPConfig.Transport sipProxy := conf.SIPConfig.SIPProxy remoteaddr := icsnet.NewNetAddrWithIPAddr(sipProxy) localAddrStr := fmt.Sprintf("0.0.0.0:%d", sipPort) localAddr := icsnet.NewNetAddrWithIPAddr(localAddrStr) switch strings.ToUpper(transport) { case "UDP": sm.SIPNeter = icsnet.NewUDP(&localAddr, &remoteaddr) case "TCP": sm.SIPNeter = icsnet.NewTCP(&localAddr, &remoteaddr) default: l.Print(icslog.LOG_LEVEL_FATAL, -1, "No compatible transport. Check the configuration") return nil } /* cerr := sm.SIPNeter.Connect() if cerr != nil { l.Print(icslog.LOG_LEVEL_FATAL, -1, cerr.GetMessage()) return nil } */ lerr := sm.SIPNeter.Listen() if lerr != nil { l.Printf(icslog.LOG_LEVEL_FATAL, -1, "Listening failed: %s", lerr.GetError()) return nil } l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening SIP %s port[%d]", transport, sipPort) /* //start bot-command listen commandValue := strings.ToUpper(conf.CommandConfig.Value) commandPort := conf.CommandConfig.Port commandTransport := conf.CommandConfig.Transport if strings.Compare("TRUE", commandValue) == 0 { commandLocalAddrStr := fmt.Sprintf("0.0.0.0:%d", commandPort) commandLocalAddr := icsnet.NewNetAddrWithIPAddr(commandLocalAddrStr) switch strings.ToUpper(commandTransport) { case "UDP": sm.CommNeter = icsnet.NewUDP(&commandLocalAddr, nil) case "TCP": sm.CommNeter = icsnet.NewTCP(&commandLocalAddr, nil) default: l.Print(icslog.LOG_LEVEL_FATAL, -1, "Bot-Command listening error. No compatible transport. Check the configuration") return nil } lerr = sm.CommNeter.Listen() if lerr != nil { l.Printf(icslog.LOG_LEVEL_FATAL, -1, "%s", lerr.GetError()) return nil } l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening Bot-Command %s port[%d]", commandTransport, commandPort) } */ sm.sessions = getSessionInstance(&sm.SIPNeter) //EventH. Create Event Array sm.event = icsevent.NewEventH() return sm } func (sm *SessionManager) Load() { sm.event.Init() //for iter, session := range sm.sessions { for _, session := range sm.sessions { //l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "333 %d", iter) go session.Run() } } func (sm *SessionManager) Close() { for iter := 0; iter < channelNum; iter++ { sm.sessions[iter].RemoveSession() } sm.SIPNeter.Close() } func (sm *SessionManager) Run() (icserr *icserror.IcsError) { l := icslog.GetIcsLog() conf := icsconf.GetIcsConfig() svc := icssvc.GetServiceStatus() for !svc.GetExit() || !svc.GetStop() { data, addr, len, rerr := sm.SIPNeter.ReadSIP() if rerr != nil { return rerr } //fmt.Println("RECVED>>>", addr, len, string(data)) l.Printf(icslog.LOG_LEVEL_INFO, -1, "Recved Data[%d] [%s]->[%s]>\n%s", len, addr.String(), sm.SIPNeter.LocalAddr().String(), string(data[:len])) sip := icspacketparser.NewSIP() sip.SipParser(data) if icspacketparser.ICS_SIP_METHOD_NOT_FOUND == sip.Method { //not found sip. maybe abnormal use l.Printf(icslog.LOG_LEVEL_INFO, -1, "icspacketparser.ICS_SIP_METHOD_NOT_FOUND-%s", string(data)) continue } else { // fmt.Println("메서드", sip.Method.String()) // if sip.Method == icspacketparser.ICS_SIP_METHOD_INVITE { // // conf := icsconf.GetIcsConfig() // // TODO - send bye // // defer func() { // // if err := recover(); err != nil { // // l.Printf(icslog.LOG_LEVEL_WARN, =1, "%s \n%s", // // icserror.ICSERRNETNotConnectError.GetMessage(), debug.Stack()) // // } // // }() // l.Printf(icslog.LOG_LEVEL_INFO, -1, "sip 내용 전달! %+v", sip) // // ip := strings.Split(conf.SIPConfig.SIPProxy, ":")[0] // // port, cerr := strconv.Atoi(strings.Split(conf.SIPConfig.SIPProxy, ":")[1]) // // if cerr != nil { // // fmt.Println("cerr err") // // } // // iport := fmt.Sprintf("%s:%d", ip, port) // // fmt.Println(ip, port) // sipPort := conf.SIPConfig.Port // // transport := conf.SIPConfig.Transport // sipProxy := conf.SIPConfig.SIPProxy // remoteaddr := icsnet.NewNetAddrWithIPAddr(sipProxy) // localAddrStr := fmt.Sprintf("192.168.0.4:%d", sipPort) // localAddr := icsnet.NewNetAddrWithIPAddr(localAddrStr) // t := icsnet.NewUDP(&localAddr, &remoteaddr) // // fmt.Println("local ", t.LocalAddr().String()) // fmt.Println("remote ", t.RemoteAddr().String()) // // sendSIP := []string{data[:]} // // for _, elem := range data { // sent, err := t.WriteSIP([]byte(data)) // if err != nil { // fmt.Println(err) // } // // } // // wlen, werr := t.WriteSIP([]byte(data)) // // if werr != nil { // // l.Print(icslog.LOG_LEVEL_FATAL, -1, werr.GetMessage()) // // // s.SetAgentStatus(STATUS_AGENT_READY) // // // return werr // // } // fmt.Printf("send data \r\n%s, \r\n %d\r\n", string(data), sent) // } else { if SessionAvailableSipMethod(&sip) { l.Printf(icslog.LOG_LEVEL_DEBUG, -1, "Session Processing Method-[%s, %s, %s]", sip.Method, sip.ResType, sip.Cseq) s, serr := FindSession(sip) if serr != nil { //not found session, create new name1 := strings.SplitN(sip.To, "@", 2) name2 := strings.SplitN(name1[0], ":", 2) agentname := name2[1] s, serr = AllocSession(agentname, sip.GetCallID()) if serr != nil { l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Licensed Session number[%d:%s] is EXCEEDED-%s", conf.GetChannelNum(), agentname, serr.GetMessage()) if conf.Representative.Value && sip.Source == "486" { l.Printf(icslog.LOG_LEVEL_ERROR, -1, "All Agent Calling!!!!!") sipPort := conf.SIPConfig.Port // sipProxy := conf.SIPConfig.SIPProxy transport := conf.SIPConfig.Transport // remoteaddr := icsnet.NewNetAddrWithIPAddr(sipProxy) // localAddrStr := fmt.Sprintf("0.0.0.0:%d", sipPort) // localAddr := icsnet.NewNetAddrWithIPAddr(localAddrStr) ////////////////////////////////////////////// ip := conf.InfoConfig.ServerIP ackMethod := fmt.Sprintf("sip:01025670081@%s;transport=%s", "192.168.0.222:5090", transport) reqAck := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_ACK, ackMethod) maxforwards := "70" // s.uri = fmt.Sprintf("sip:%s@%s", conf.Representative.Name, ip) // l.Printf(icslog.LOG_LEVEL_INFO, -1, "Set URI [%s]", s.uri) contact := fmt.Sprintf("", conf.Representative.Name, ip, sipPort, transport) userAgent := conf.InfoConfig.Product allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE" supported := "timer,path,replaces" for _, viav := range sip.Via { reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, viav) } reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, sip.From) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, sip.To) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, sip.CallID) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, sip.Cseq) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported) reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, "0") reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR) // wlen, werr := (*s.sipNeter).WriteSIPTo([]byte(reqAck.String()), s.remoteSIPAddr) wlen, werr := (sm.SIPNeter).WriteSIP([]byte(reqAck.String())) if werr != nil { l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage()) return werr } l.Printf(icslog.LOG_LEVEL_INFO, -1, "Sent Data(%d) [%s]->[%s]>\n%s", wlen, (sm.SIPNeter).LocalAddr().String(), (sm.SIPNeter).RemoteAddr().String(), reqAck.String()) ////////////////////////////////////////////// } continue } l.Printf(icslog.LOG_LEVEL_INFO, -1, "Session Allocated. Session ID[%d] Call ID[%s]", s.ID, sip.GetCallID()) s.SetSessionMethod(sip) //session start s.Start() } else { //found session l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Session found [%s][%s]", sip.GetCallID(), s.callID) if sip.Method == icspacketparser.ICS_SIP_METHOD_INVITE { s.SetCallID(sip.GetCallID()) } // 대표번호 if sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 || strings.SplitN(sip.Cseq, " ", 2)[1] == "INVITE" { s.SetCallID(sip.GetCallID()) // representative if conf.Representative.Value { sip.SetToRep() sip.SetTo(s.AgentName) // if sip.Source == "486" { // l.Printf(icslog.LOG_LEVEL_ERROR, -1, "All Agent Calling!!!!!") // fmt.Println("##### All Agent Clling!!!!!! ") // s.Res486Ack(&sip) // continue // } } } if s.CheckAutomata(&sip) { s.SetSessionMethod(sip) } else { l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Not Allowed Method(%d)", s.MethodAutomata) //TODO : response 400 error continue } // if conf.Representative.Value && sip.Source == "486" { // l.Printf(icslog.LOG_LEVEL_ERROR, -1, "All Agent Calling!!!!!") // fmt.Println("##### All Agent Clling!!!!!! ") // s.Res486Ack(&sip) // continue // } //if cancel ACK or bye res, remove the session if s.MethodAutomata == ICS_SIP_AUTOMATA_CANCEL && sip.Method == icspacketparser.ICS_SIP_METHOD_ACK { s.Stop() serr := s.RemoveSession() if serr != nil { l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "RemoveSession Error %s", serr.GetMessage()) } else { l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Session Removed") } continue } } //post the sip event to session h := icsevent.NewEventH() evt, evtErr := h.AllocEvent(sip) if evtErr != nil { return evtErr } perr := h.PostEvent(s.ID, evt) //perr := h.PostEvent(int(s.GetSessionID()), evt) if perr == nil { l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Post SIP event[%d] to Session[%03d]", evt.ID, s.ID) } else { l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to post SIP event[%d] to Session[%03d] - %s", evt.ID, s.ID, perr.GetError()) } } else { // no session switch sip.Method { case icspacketparser.ICS_SIP_METHOD_OPTIONS: l.Printf(icslog.LOG_LEVEL_INFO, -1, "%v", sip) case icspacketparser.ICS_SIP_METHOD_SIP20: if strings.Contains(strings.ToUpper(sip.Cseq), "OPTIONS") { //l.Printf(icslog.LOG_LEVEL_INFO, -1, "%v", sip) } else { l.Printf(icslog.LOG_LEVEL_INFO, -1, "%v", sip) } default: l.Printf(icslog.LOG_LEVEL_INFO, -1, "%v", sip) } } // } } data = nil } return nil } //bot-command manager func (sm *SessionManager) RunBotCommandMNG() (icserr *icserror.IcsError) { l := icslog.GetIcsLog() conf := icsconf.GetIcsConfig() //start bot-command listen commandPort := conf.CommandConfig.Port commandTransport := conf.CommandConfig.Transport commandLocalAddrStr := fmt.Sprintf("0.0.0.0:%d", commandPort) commandLocalAddr := icsnet.NewNetAddrWithIPAddr(commandLocalAddrStr) var cmdErr *icserror.IcsError sm.CommNet, cmdErr = icsnet.ListenAndServeTCP(&commandLocalAddr, nil, "\r\n\r\n", BotCommand) if cmdErr != nil { l.Printf(icslog.LOG_LEVEL_FATAL, -1, "%s", cmdErr.GetError()) return nil } l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening Bot-Command %s port[%d]", commandTransport, commandPort) /* for !svc.GetExit() || !svc.GetStop() { } */ return nil } func BotCommand(t *icsnet.IcsTCPNet, bufend string) { l := icslog.GetIcsLog() defer t.Close() for { ttsHeader, rlen, rerr := t.ReadS(86, bufend) if rerr != nil { if rerr.GetError() != io.EOF { l.Printf(icslog.LOG_LEVEL_ERROR, -1, "[Bot Command] ReadS Error! - %s[%d:%s]", rerr.GetError(), rlen, len(ttsHeader)) } break } else { l.Printf(icslog.LOG_LEVEL_INFO, -1, "Recved Bot Command(%s)", ttsHeader) ttscmd := binary.LittleEndian.Uint32(ttsHeader[0:]) ttsrc := binary.LittleEndian.Uint32(ttsHeader[4:]) ttspl := binary.LittleEndian.Uint64(ttsHeader[8:]) agentname := string(ttsHeader[16:]) //remove null terminator n := bytes.Index([]byte(agentname), []byte{0}) agentName := string([]byte(agentname)[:n]) telno := string(ttsHeader[36:]) m := bytes.Index([]byte(telno), []byte{0}) telNo := string([]byte(telno)[:m]) s := findSessionWithAgentName2(agentName) if s == nil { l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Not found session - %s", agentName) return } l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Bot Command(%d) - [%s:%d]", rlen, agentName, ttscmd) switch ttscmd { case recorddata.TTS_COMMAND: l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS command") //fmt.Println("374LINE", ttscmd, ttsrc, ttspl, agentName) //recv tts data tts, rlen, rerr := t.Read(int(ttspl)) if rerr != nil { l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError()) return } l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(tts)) ////////////////////// //RTP start l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP Callback timer %+v", s.RTPSenderCallBackTimer) s.RTPSenderCallBackTimer.Stop() s.m.Lock() s.tts = make([]byte, int(ttspl)) copy(s.tts, tts) s.m.Unlock() /* n := time.Now() filename := fmt.Sprintf("./%daaabbb%d-2.pcm", s.ID, n.Nanosecond()) ttsfile, ferr := os.OpenFile(filename, os.O_CREATE|os.O_RDWR|os.O_APPEND|os.O_TRUNC|os.O_SYNC, os.FileMode(0644)) if ferr != nil { fmt.Println(ferr) os.Exit(1) } ttsfile.Write(tts) ttsfile.Close() */ //s.tts = tts //s.txCnt = 0 //s.callStartTime = time.Now() s.RTPSenderCallBackTimer.Start() case recorddata.BYE_COMMAND: l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Recved BYE command") //fmt.Println("393LINE", ttscmd, ttsrc, ttspl, agentName) if int(ttspl) > 0 { //recv tts data tts, rlen, rerr := t.Read(int(ttspl)) if rerr != nil { l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError()) return } l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Read T: %v", t) l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(tts)) ////////////////////// //RTP start l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP Callback timer %+v", s.RTPSenderCallBackTimer) s.RTPSenderCallBackTimer.Stop() s.m.Lock() s.tts = make([]byte, int(ttspl)) copy(s.tts, tts) //s.tts = tts s.m.Unlock() //s.txCnt = 0 //s.callStartTime = time.Now() s.RTPSenderCallBackTimer.Start() //request bye sleeptime := int(ttspl) / 16 time.Sleep(time.Millisecond * time.Duration(sleeptime+200)) agentStatus := s.GetAgentStatus() //l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Agent Status: %d", agentStatus) if agentStatus == STATUS_AGENT_BUSY { s.RequestBYE(s.InviteSIP) s.SetAgentStatus(STATUS_AGENT_BYEING) fmt.Println("AGENT_STATUS : ", s.GetAgentStatus()) } s.BotStatus = ttscmd } else { if s.InviteSIP == nil { agentStatus := s.GetAgentStatus() if agentStatus == STATUS_AGENT_BUSY { s.SetAgentStatus(STATUS_AGENT_ERROR) } } else { s.RequestBYE(s.InviteSIP) } } case recorddata.DTMF_COMMAND: l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Recved DTMF command") //fmt.Println("374LINE", ttscmd, ttsrc, ttspl, agentName) //recv tts data tts, rlen, rerr := t.Read(int(ttspl)) if rerr != nil { l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError()) fmt.Println("error : ", rerr.GetError()) return } l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(tts)) ////////////////////// //RTP start l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP Callback timer %+v", s.RTPSenderCallBackTimer) s.RTPSenderCallBackTimer.Stop() s.m.Lock() s.tts = make([]byte, int(ttspl)) copy(s.tts, tts) s.m.Unlock() s.BotStatus = ttscmd s.RTPSenderCallBackTimer.Start() case recorddata.REFER_COMMAND: l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved REFER command %+v", ttscmd) //fmt.Println("393LINE", ttscmd, ttsrc, ttspl, agentName) if int(ttspl) > 0 { //recv tts data tts, rlen, rerr := t.Read(int(ttspl)) if rerr != nil { l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError()) return } l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(tts)) ////////////////////// //RTP start l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP Callback timer %+v", s.RTPSenderCallBackTimer) s.RTPSenderCallBackTimer.Stop() s.m.Lock() s.tts = make([]byte, int(ttspl)) copy(s.tts, tts) //s.tts = tts s.m.Unlock() //s.txCnt = 0 //s.callStartTime = time.Now() s.RTPSenderCallBackTimer.Start() //request bye sleeptime := int(ttspl) / 16 time.Sleep(time.Millisecond * time.Duration(sleeptime+200)) agentStatus := s.GetAgentStatus() //l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Agent Status: %d", agentStatus) if agentStatus == STATUS_AGENT_BUSY { s.RequestRefer(telNo, s.InviteSIP) s.SetAgentStatus(STATUS_AGENT_BYEING) fmt.Println("AGENT_STATUS : ", s.GetAgentStatus()) } s.BotStatus = ttscmd } else { if s.InviteSIP == nil { agentStatus := s.GetAgentStatus() if agentStatus == STATUS_AGENT_BUSY { s.SetAgentStatus(STATUS_AGENT_ERROR) } } else { s.RequestRefer(telNo, s.InviteSIP) } } default: l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "485LINE %+v, %+v, %+v, %s", ttscmd, ttsrc, ttspl, agentName) } } fmt.Println("418LINE rlen", rlen, rerr) } }