|
|
|
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("<sip:%s@%s:%d;transport=%s>", 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)
|
|
|
|
}
|
|
|
|
}
|