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.
487 lines
13 KiB
Go
487 lines
13 KiB
Go
package icssessionmanager
|
|
|
|
import (
|
|
"runtime"
|
|
"runtime/debug"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icserror"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icslog"
|
|
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
|
|
)
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//session operator
|
|
func findSessionWithCallID(callId string) *IcsSession {
|
|
sessions := getSessionInstance(nil)
|
|
for _, session := range sessions {
|
|
session.m.Lock()
|
|
// fmt.Printf("findSessionWithCallID %d [%s][%s]\n", iter, session.callID, callId)
|
|
|
|
if strings.Compare(session.callID, callId) == 0 {
|
|
//if strings.Compare(session.callID, callId) == 0 || strings.Compare(session.regiCallID, callId) == 0 {
|
|
// fmt.Printf("findSessionWithCallID session found! %d [%s][%s]\n", iter, session.callID, callId)
|
|
session.m.Unlock()
|
|
return session
|
|
}
|
|
session.m.Unlock()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func findSessionWithFromURI(uri string) *IcsSession {
|
|
sessions := getSessionInstance(nil)
|
|
for _, session := range sessions {
|
|
session.m.Lock()
|
|
//fmt.Println("findSessionWithFromURI", session.uri)
|
|
if strings.Contains(session.uri, uri) {
|
|
session.m.Unlock()
|
|
return session
|
|
}
|
|
session.m.Unlock()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func findSessionWithRTPPort(srcPort int, dstPort int) *IcsSession {
|
|
sessions := getSessionInstance(nil)
|
|
for _, session := range sessions {
|
|
session.m.Lock()
|
|
if (session.srcPort == srcPort && session.dstPort == dstPort) || (session.srcPort == dstPort && session.dstPort == srcPort) {
|
|
session.m.Unlock()
|
|
return session
|
|
}
|
|
session.m.Unlock()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func findSessionWithAgentName(agentName string) *IcsSession {
|
|
sessions := getSessionInstance(nil)
|
|
for _, session := range sessions {
|
|
session.m.Lock()
|
|
//fmt.Printf(">>>>findSessionWithAgentName: name: %s, name2: %s, arg: %s\n", session.AgentName, session.AgentName2, agentName)
|
|
if strings.Compare(session.AgentName, agentName) == 0 {
|
|
session.m.Unlock()
|
|
return session
|
|
}
|
|
session.m.Unlock()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// representative
|
|
func findSessionWithSessionStatus(callID string) *IcsSession {
|
|
conf := icsconf.GetIcsConfig()
|
|
sessions := getSessionInstance(nil)
|
|
for idx, session := range sessions {
|
|
session.m.Lock()
|
|
// fmt.Println(session.AgentName, session.agentStatus)
|
|
if strings.Compare(conf.AgentConfig[idx].Value, "true") == 0 && session.agentStatus == 64 {
|
|
// session.callID = callID
|
|
session.m.Unlock()
|
|
return session
|
|
}
|
|
session.m.Unlock()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func findSessionWithSessionStatusForINVITE() *IcsSession {
|
|
conf := icsconf.GetIcsConfig()
|
|
sessions := getSessionInstance(nil)
|
|
for idx, session := range sessions {
|
|
session.m.Lock()
|
|
if strings.Compare(conf.AgentConfig[idx].Value, "true") == 0 && session.agentStatus == 64 {
|
|
session.m.Unlock()
|
|
return session
|
|
}
|
|
session.m.Unlock()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func findSessionWithAgentName2(agentName string) *IcsSession {
|
|
sessions := getSessionInstance(nil)
|
|
for _, session := range sessions {
|
|
session.m.Lock()
|
|
//fmt.Printf(">>>>findSessionWithAgentName2: name: %s, name2: %s, arg: %s\n", session.AgentName, session.AgentName2, agentName)
|
|
if strings.Compare(session.AgentName2, agentName) == 0 {
|
|
session.m.Unlock()
|
|
return session
|
|
}
|
|
session.m.Unlock()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
/* 미사용 코드로 임시 주석 처리 ( csma 210512 )
|
|
func FindSessionID(sip icspacketparser.SIP) (IcsSessionID, *icserror.IcsError) {
|
|
callID := sip.GetCallID()
|
|
if len(callID) > 0 {
|
|
session := findSessionWithCallID(callID)
|
|
if session != nil {
|
|
return IcsSessionID(session.ID), nil
|
|
}
|
|
}
|
|
|
|
return IcsSessionID(-1), icserror.ICSERRSESSNotFoundSession
|
|
}
|
|
*/
|
|
|
|
func FindSession(data interface{}) (*IcsSession, *icserror.IcsError) {
|
|
//func FindSession(sip icspacketparser.SIP) (*IcsSession, *icserror.IcsError) {
|
|
l := icslog.GetIcsLog()
|
|
conf := icsconf.GetIcsConfig()
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
l.Printf(icslog.LOG_LEVEL_WARN, -1, "%s\n%s",
|
|
icserror.ICSERRNETNotConnectError.GetMessage(), debug.Stack())
|
|
}
|
|
}()
|
|
switch v := data.(type) {
|
|
case icspacketparser.SIP:
|
|
sip := v
|
|
callID := sip.GetCallID()
|
|
uri := sip.GetURI()
|
|
name1 := strings.SplitN(sip.To, "@", 2)
|
|
name2 := strings.SplitN(name1[0], ":", 2)
|
|
agentname := name2[1]
|
|
/*
|
|
if sip.Method == icspacketparser.ICS_SIP_METHOD_BYE || sip.Method == icspacketparser.ICS_SIP_METHOD_CANCEL {
|
|
//fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>", callID)
|
|
}
|
|
*/
|
|
|
|
// if conf.Representative.Value && sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 && strings.SplitN(sip.Cseq, " ", 2)[1] == "INVITE" {
|
|
if conf.Representative.Value && sip.Method == icspacketparser.ICS_SIP_METHOD_INVITE { // invite, botstatus
|
|
if len(agentname) > 0 {
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "FindSession>findSessionWithAgentName> agent name[%s]", agentname)
|
|
// session := findSessionWithCallID(callID)
|
|
session := findSessionWithSessionStatus(callID) // 대표번호 agentname
|
|
if session != nil {
|
|
return session, nil
|
|
}
|
|
}
|
|
} else if conf.Representative.Value && sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 && strings.SplitN(sip.Cseq, " ", 2)[1] == "INVITE" { // callid
|
|
if len(callID) > 0 {
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "FindSession>findSessionWithCallID> callid [%s]", callID)
|
|
session := findSessionWithCallID(callID)
|
|
if session != nil {
|
|
return session, nil
|
|
}
|
|
}
|
|
} else {
|
|
if len(callID) > 0 {
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "FindSession>findSessionWithCallID> callid [%s]", callID)
|
|
session := findSessionWithCallID(callID)
|
|
if session != nil {
|
|
return session, nil
|
|
}
|
|
}
|
|
// if len(agentname) > 0 {
|
|
// l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "FindSession>findSessionWithAgentName> agent name[%s]", agentname)
|
|
// session := findSessionWithAgentName(agentname)
|
|
// if session != nil {
|
|
// return session, nil
|
|
// }
|
|
// }
|
|
if len(uri) > 0 {
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "FindSession>findSessionWithFromURI> uri [%s]", uri)
|
|
//fmt.Println("findsession", uri)
|
|
session := findSessionWithFromURI(uri)
|
|
if session != nil {
|
|
return session, nil
|
|
}
|
|
}
|
|
}
|
|
case icspacketparser.RTP:
|
|
rtp := v
|
|
srcPort := rtp.SrcAddr.Port
|
|
dstPort := rtp.DstAddr.Port
|
|
session := findSessionWithRTPPort(srcPort, dstPort)
|
|
if session != nil {
|
|
return session, nil
|
|
}
|
|
}
|
|
|
|
return nil, icserror.ICSERRSESSNotFoundSession
|
|
}
|
|
|
|
/* 미사용 코드로 임시 주석 처리 ( csma 200512 )
|
|
func AllocSessionID(callId string, direction bool) (IcsSessionID, *icserror.IcsError) {
|
|
if len(callId) == 0 {
|
|
return IcsSessionID(-1), icserror.ICSERRInvalidParam
|
|
}
|
|
|
|
sessions := getSessionInstance()
|
|
|
|
var id int
|
|
for _, session := range sessions {
|
|
id++
|
|
if len(session.callId) == 0 {
|
|
session.callId = callId
|
|
session.direction = direction
|
|
return IcsSessionID(session.ID), nil
|
|
}
|
|
}
|
|
|
|
if id >= channelNum {
|
|
return IcsSessionID(-1), icserror.ICSERRSESSMaxSessionNumber
|
|
}
|
|
|
|
return IcsSessionID(-1), icserror.ICSERRSESSNotFoundSession
|
|
}
|
|
*/
|
|
|
|
func goid() int {
|
|
var buf [64]byte
|
|
n := runtime.Stack(buf[:], false)
|
|
idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
|
|
id, err := strconv.Atoi(idField)
|
|
if err != nil {
|
|
return -1
|
|
}
|
|
return id
|
|
}
|
|
|
|
func AllocSession(station, callID string) (*IcsSession, *icserror.IcsError) {
|
|
if len(callID) == 0 {
|
|
return nil, icserror.ICSERRInvalidParam
|
|
}
|
|
|
|
l := icslog.GetIcsLog()
|
|
sessions := getSessionInstance(nil)
|
|
|
|
var id int = 0
|
|
for _, session := range sessions {
|
|
id++
|
|
session.m.Lock()
|
|
if len(session.callID) == 0 && strings.Compare(station, session.AgentName) == 0 {
|
|
session.callID = callID
|
|
|
|
session.m.Unlock()
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID,
|
|
"Session Allocated[%d] Call ID: %s, Station: %s==========================",
|
|
session.goroutineID, session.callID, station)
|
|
return session, nil
|
|
}
|
|
session.m.Unlock()
|
|
}
|
|
|
|
if id >= channelNum {
|
|
return nil, icserror.ICSERRSESSMaxSessionNumber
|
|
}
|
|
|
|
return nil, icserror.ICSERRSESSNotFoundSession
|
|
}
|
|
|
|
func (s *IcsSession) SetCallID(callID string) {
|
|
s.callID = callID
|
|
}
|
|
|
|
func (s *IcsSession) CloseSession() *icserror.IcsError {
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *IcsSession) RemoveSession() *icserror.IcsError {
|
|
l := icslog.GetIcsLog()
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
switch v := err.(type) {
|
|
case error:
|
|
icserror.ICSERRNETNotConnectError.SetError(v)
|
|
l.Printf(icslog.LOG_LEVEL_WARN, s.ID,
|
|
"PANIC! %s\n%s",
|
|
icserror.ICSERRNETNotConnectError.GetError().Error(), string(debug.Stack()))
|
|
default:
|
|
l.Print(icslog.LOG_LEVEL_WARN, s.ID, icserror.ICSERRNETNotConnectError.GetMessage())
|
|
}
|
|
}
|
|
}()
|
|
//s.VoiceNeter.Close()
|
|
//s.CallSignalNeter.Close()
|
|
|
|
//id := s.ID
|
|
//s = &IcsSession{ID: id}
|
|
|
|
//s.rxFile.Close()
|
|
//s.txFile.Close()
|
|
|
|
if s.CurrentSIP.Method == icspacketparser.ICS_SIP_METHOD_SIP20 && strings.Contains(s.CurrentSIP.Cseq, " REGISTER") {
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "REGI!!!")
|
|
s.callID = ""
|
|
return nil
|
|
} else {
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "--------------------------")
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Call duration : %d ms", time.Since(s.callStartTime)/time.Millisecond)
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Rx packets : %d", s.rxCnt)
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Tx packets : %d", s.txCnt)
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Call Ended. Station: %s Call ID: %s", s.AgentName, s.callID)
|
|
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "==========================")
|
|
|
|
// fmt.Println("### s.readTimer Stop")
|
|
// s.readTimer.Stop()
|
|
// s.mychannel <- true
|
|
// if s.rtpMediaNeter != nil {
|
|
// s.rtpMediaNeter.Close()
|
|
// s.rtpMediaNeter = nil
|
|
// }
|
|
// fmt.Println("### s.readTimer Stop", s.AgentName)
|
|
s.RTPSenderCallBackTimer.Stop()
|
|
if s.rtpMediaNeter != nil {
|
|
// fmt.Println("voice neter nil!!")
|
|
s.rtpMediaNeter.Close()
|
|
s.rtpMediaNeter = nil
|
|
}
|
|
if s.rtcpMediaNeter != nil {
|
|
s.rtcpMediaNeter.Close()
|
|
s.rtcpMediaNeter = nil
|
|
}
|
|
|
|
}
|
|
|
|
e := &IcsSession{}
|
|
s.m.Lock()
|
|
s.eventSystem.ClearJob()
|
|
|
|
/*
|
|
s.AgentConf = nil
|
|
s.AgentInfo = nil
|
|
s.AgentName = ""
|
|
s.AgentName2 = ""
|
|
*/
|
|
|
|
s.callID = ""
|
|
|
|
s.tts = nil
|
|
|
|
s.srcPort = e.srcPort
|
|
s.dstPort = e.dstPort
|
|
s.direction = e.direction
|
|
s.isStart = false
|
|
s.isFoundPayload = false
|
|
//s.RxConverter.Close()
|
|
//s.TxConverter.Close()
|
|
if s.RxConverter != nil {
|
|
s.RxConverter.Close()
|
|
s.RxConverter = nil
|
|
}
|
|
if s.TxConverter != nil {
|
|
s.TxConverter.Close()
|
|
s.TxConverter = nil
|
|
}
|
|
s.txSeq = -1
|
|
s.rxSeq = -1
|
|
s.MethodAutomata = 32767
|
|
// s.referto = ""
|
|
s.SetAgentStatus(STATUS_AGENT_READY)
|
|
s.SetRegisterStatus(STATUS_REGISTER_READY)
|
|
// fmt.Println("REMOVE SESSION STATUS: ", s.GetAgentStatus())
|
|
s.m.Unlock()
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetSession(sessionID IcsSessionID) (*IcsSession, *icserror.IcsError) {
|
|
if sessionID < IcsSessionID(0) {
|
|
return nil, icserror.ICSERRInvalidParam
|
|
}
|
|
|
|
sessions := getSessionInstance(nil)
|
|
return sessions[int(sessionID)], nil
|
|
}
|
|
|
|
func (s IcsSession) GetSessionID() IcsSessionID {
|
|
return IcsSessionID(s.ID)
|
|
}
|
|
|
|
func (s *IcsSession) CheckSignalMethod(sip icspacketparser.SIP) *icserror.IcsError {
|
|
if s.CheckAutomata(&sip) {
|
|
if s.MethodAutomata != ICS_SIP_AUTOMATA_CANCEL {
|
|
s.SetSessionMethod(sip)
|
|
}
|
|
} else {
|
|
//fmt.Println("^^^^^", "unMatched Automata", s.MethodAutomata, sip.Method)
|
|
}
|
|
|
|
if sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 && strings.Contains(sip.Cseq, " BYE") || s.MethodAutomata == ICS_SIP_AUTOMATA_CANCEL && sip.Method == icspacketparser.ICS_SIP_METHOD_ACK {
|
|
//fmt.Println("^^^^^", "call s.RemoveSession() sip.Method, s.MethodAutomata ", sip.Method, s.MethodAutomata)
|
|
serr := s.RemoveSession()
|
|
if serr != nil {
|
|
//serr.Print()
|
|
return serr
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//
|
|
func (s *IcsSession) SetTimestamp(now time.Time) {
|
|
s.lastTimestamp = now
|
|
}
|
|
|
|
func (s IcsSession) GetPayloadType() icspacketparser.PayloadType {
|
|
return s.payloadType
|
|
}
|
|
|
|
func (s *IcsSession) GetDirection() bool {
|
|
return s.direction
|
|
}
|
|
|
|
func (s *IcsSession) SetDirection(direction bool) {
|
|
s.direction = direction
|
|
}
|
|
|
|
func (s *IcsSession) SetAgentInfo(agentInfo *icsconf.AgentInfo) {
|
|
s.AgentInfo = agentInfo
|
|
}
|
|
|
|
func FindAgentInfo(agentID string) *icsconf.AgentInfo {
|
|
conf := icsconf.GetIcsConfig()
|
|
|
|
//a := strings.SplitN(agentID, string(0), 2)
|
|
for _, agentconf := range conf.VoiceAgentConfig.AgentInfo {
|
|
//for _, agentconf := range conf.AgentConfig {
|
|
//fmt.Printf("308LINE iter: %d, [%v] [%v] [%v]\n", iter, []byte(agentconf.Name), []byte(agentID), []byte(a[0]))
|
|
if strings.Contains(agentID, agentconf.Name) {
|
|
//fmt.Println(">>>>", iter, agentconf.Name)
|
|
return &agentconf
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *IcsSession) SetAgentConfig(agentConfig *icsconf.AgentConfig) {
|
|
s.AgentConf = agentConfig
|
|
}
|
|
|
|
func FindAgentConfig(agentID string) *icsconf.AgentConfig {
|
|
conf := icsconf.GetIcsConfig()
|
|
|
|
//a := strings.SplitN(agentID, string(0), 2)
|
|
for _, agentconf := range conf.AgentConfig {
|
|
//for _, agentconf := range conf.AgentConfig {
|
|
//fmt.Printf("308LINE iter: %d, [%v] [%v] [%v]\n", iter, []byte(agentconf.Name), []byte(agentID), []byte(a[0]))
|
|
if strings.Contains(agentID, agentconf.Name) {
|
|
//fmt.Println(">>>>", iter, agentconf.Name)
|
|
return &agentconf
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|