package icssessionmanager import ( "fmt" "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 len(agentname) > 0 { l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "FindSession>findSessionWithAgentName> agent name[%s]", agentname) session := findSessionWithSessionStatus(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 }