|
|
|
package icsapp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icsconf"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icserror"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icsevent"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icshttp"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icshttpclient"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icslog"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icsnet"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icssessionmanager"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icssvc"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/icsws"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/recorddata"
|
|
|
|
"gitlab.com/cinnamon/voiceagent/recorddata/readcallsignal"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
LINEEND1 = "\r\n"
|
|
|
|
LINEEND2 = "EOM"
|
|
|
|
)
|
|
|
|
|
|
|
|
type IcsExec struct {
|
|
|
|
service *icssvc.IcsService
|
|
|
|
config *icsconf.IcsConfig
|
|
|
|
httpsrv *icshttp.Router
|
|
|
|
hbNet *icsnet.IcsTCPNet
|
|
|
|
sttNet *icsnet.IcsTCPNet
|
|
|
|
csNet *icsnet.IcsTCPNet
|
|
|
|
ttsNet *icsnet.IcsTCPNet
|
|
|
|
cmdNet *icsnet.IcsTCPNet
|
|
|
|
}
|
|
|
|
|
|
|
|
func Init(conf *icsconf.IcsConfig) (e *IcsExec) {
|
|
|
|
e = &IcsExec{}
|
|
|
|
e.service = icssvc.GetServiceStatus()
|
|
|
|
e.config = conf
|
|
|
|
e.httpsrv = icshttp.NewRouter()
|
|
|
|
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
|
|
|
|
func (exe IcsExec) Execute() *icserror.IcsError {
|
|
|
|
l := icslog.GetIcsLog()
|
|
|
|
logFile, _ := os.Create("track" + time.Now().Format("20060102_150405") + ".log")
|
|
|
|
syscall.Dup2(int(logFile.Fd()), 2)
|
|
|
|
for !exe.service.GetExit() {
|
|
|
|
for exe.service.GetStop() {
|
|
|
|
time.Sleep(time.Millisecond)
|
|
|
|
}
|
|
|
|
|
|
|
|
//init session manager and run
|
|
|
|
sm := icssessionmanager.NewSessionManager()
|
|
|
|
sm.Load()
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
//start Heart beat TCP server
|
|
|
|
// hbDone := make(chan *icserror.IcsError)
|
|
|
|
// if exe.config.HeartBeat.Value {
|
|
|
|
// go func() {
|
|
|
|
// saddr := fmt.Sprintf(":%d", exe.config.HeartBeat.Port)
|
|
|
|
// hbladdr := icsnet.NewNetAddrWithIPAddr(saddr)
|
|
|
|
// var hbErr *icserror.IcsError
|
|
|
|
// //set handler
|
|
|
|
// exe.hbNet, hbErr = icsnet.ListenAndServeTCP(&hbladdr, nil, LINEEND1, TCPConnHandlerHeartBeat)
|
|
|
|
// if hbErr != nil {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Heart beat Listen - %s", hbErr.GetError())
|
|
|
|
// hbDone <- hbErr
|
|
|
|
// } else {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_INFO, -1, "Liesting Heart beat - %s", saddr)
|
|
|
|
// }
|
|
|
|
// }()
|
|
|
|
// }
|
|
|
|
|
|
|
|
// /////////////////////////////////////////////////////////////////////
|
|
|
|
// //start Call signal TCP server
|
|
|
|
// csDone := make(chan *icserror.IcsError)
|
|
|
|
// p1 := &exe.config.ServerConfig.CSConfig.Port
|
|
|
|
// go func() {
|
|
|
|
// //saddr := fmt.Sprintf("%s:%d", exe.config.STTConfig.SrcIP, exe.config.STTConfig.Port)
|
|
|
|
// cslAddr := icsnet.NewNetAddrWithIPPort("0.0.0.0", *p1)
|
|
|
|
// //cslAddr := icsnet.NewNetAddrWithIPPort("0.0.0.0", exe.config.AgentConfig[idx].CSConfig.Port)
|
|
|
|
// //cslAddr := icsnet.NewNetAddrWithIPPort("0.0.0.0", exe.config.AgentConfig[iter].CSConfig.Port)
|
|
|
|
// var csErr *icserror.IcsError
|
|
|
|
// //set handler
|
|
|
|
// exe.csNet, csErr = icsnet.ListenAndServeTCP(&cslAddr, nil, LINEEND2, TCPConnHandlerCS)
|
|
|
|
// if csErr != nil {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Call Signal Listen failure - %s", csErr.GetMessage())
|
|
|
|
// csDone <- csErr
|
|
|
|
// } else {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening Call Signal - %s", cslAddr)
|
|
|
|
// }
|
|
|
|
// }()
|
|
|
|
// /////////////////////////////////////////////////////////////////////
|
|
|
|
// //start STT TCP server
|
|
|
|
// sttDone := make(chan *icserror.IcsError)
|
|
|
|
// if exe.config.STTConfig.Value {
|
|
|
|
// go func() {
|
|
|
|
// saddr := fmt.Sprintf("%s:%d", exe.config.STTConfig.SrcIP, exe.config.STTConfig.Port)
|
|
|
|
// STTladdr := icsnet.NewNetAddrWithIPAddr(saddr)
|
|
|
|
// var sttErr *icserror.IcsError
|
|
|
|
// //set handler
|
|
|
|
// exe.sttNet, sttErr = icsnet.ListenAndServeTCP(&STTladdr, nil, LINEEND1, TCPConnHandlerSTT)
|
|
|
|
// if sttErr != nil {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_ERROR, -1, "STT Listen failure - %s", sttErr.GetMessage())
|
|
|
|
// sttDone <- sttErr
|
|
|
|
// } else {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening STT - %s", saddr)
|
|
|
|
// }
|
|
|
|
// //sttDone <- nil
|
|
|
|
// }()
|
|
|
|
// }
|
|
|
|
|
|
|
|
// /////////////////////////////////////////////////////////////////////
|
|
|
|
// //start TTS TCP server
|
|
|
|
// ttsDone := make(chan *icserror.IcsError)
|
|
|
|
// if exe.config.TTSConfig.Value {
|
|
|
|
// go func() {
|
|
|
|
// saddr := fmt.Sprintf("%s:%d", exe.config.TTSConfig.SrcIP, exe.config.TTSConfig.Port)
|
|
|
|
// TTSladdr := icsnet.NewNetAddrWithIPAddr(saddr)
|
|
|
|
// var ttsErr *icserror.IcsError
|
|
|
|
// //set handler
|
|
|
|
// exe.ttsNet, ttsErr = icsnet.ListenAndServeTCP(&TTSladdr, nil, LINEEND2, TCPConnHandlerTTS)
|
|
|
|
// if ttsErr != nil {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_ERROR, -1, "TTS Listen - %s", ttsErr.GetMessage())
|
|
|
|
// ttsDone <- ttsErr
|
|
|
|
// } else {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening TTS - %s", saddr)
|
|
|
|
// }
|
|
|
|
// //ttsDone <- nil
|
|
|
|
// }()
|
|
|
|
// }
|
|
|
|
|
|
|
|
// /////////////////////////////////////////////////////////////////////
|
|
|
|
// //start command TCP server
|
|
|
|
// cmdDone := make(chan *icserror.IcsError)
|
|
|
|
// if exe.config.CommandConfig.Value {
|
|
|
|
// go func() {
|
|
|
|
// saddr := fmt.Sprintf("%s:%d", exe.config.CommandConfig.SrcIP, exe.config.CommandConfig.Port)
|
|
|
|
// CMDladdr := icsnet.NewNetAddrWithIPAddr(saddr)
|
|
|
|
// var cmdErr *icserror.IcsError
|
|
|
|
// //set handler
|
|
|
|
// exe.cmdNet, cmdErr = icsnet.ListenAndServeTCP(&CMDladdr, nil, LINEEND2, TCPConnHandlerCommand)
|
|
|
|
// if cmdErr != nil {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Bot Command Listen - %s", cmdErr.GetMessage())
|
|
|
|
// cmdDone <- cmdErr
|
|
|
|
// } else {
|
|
|
|
// l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listeing Bot Command Listen - %s", saddr)
|
|
|
|
// }
|
|
|
|
// //ttsDone <- nil
|
|
|
|
// }()
|
|
|
|
// }
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
//make http handler
|
|
|
|
httpDone := make(chan error)
|
|
|
|
if exe.config.HTTPConfig.Value {
|
|
|
|
icshttp.BuildHandler(exe.httpsrv)
|
|
|
|
l.Print(icslog.LOG_LEVEL_DEBUG2, -1, "Registered http handlers")
|
|
|
|
|
|
|
|
//start http server
|
|
|
|
go func() {
|
|
|
|
saddr := fmt.Sprintf(":%d", exe.config.HTTPConfig.Port)
|
|
|
|
httpErr := http.ListenAndServe(saddr, exe.httpsrv)
|
|
|
|
if httpErr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "HTTP Listen failed - %v", httpErr)
|
|
|
|
fmt.Println("HTTP Listen failed -", httpErr)
|
|
|
|
httpDone <- httpErr
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "HTTP Listen - %s", saddr)
|
|
|
|
}
|
|
|
|
//httpDone <- nil
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
// case hbch := <-hbDone:
|
|
|
|
// if hbch != nil {
|
|
|
|
// return hbch
|
|
|
|
// }
|
|
|
|
// case sttch := <-sttDone:
|
|
|
|
// if sttch != nil {
|
|
|
|
// return sttch
|
|
|
|
// }
|
|
|
|
// /*
|
|
|
|
// case csch := <-csDone:
|
|
|
|
// if csch != nil {
|
|
|
|
// return csch
|
|
|
|
// }
|
|
|
|
// */
|
|
|
|
// case ttsch := <-ttsDone:
|
|
|
|
// if ttsch != nil {
|
|
|
|
// return ttsch
|
|
|
|
// }
|
|
|
|
// case cmdch := <-cmdDone:
|
|
|
|
// if cmdch != nil {
|
|
|
|
// return cmdch
|
|
|
|
// }
|
|
|
|
case httpch := <-httpDone:
|
|
|
|
if httpch != nil {
|
|
|
|
icserror.ICSERRAPPHTTP.SetError(httpch)
|
|
|
|
return icserror.ICSERRAPPHTTP
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TCPConnHandlerHeartBeat(t *icsnet.IcsTCPNet, bufend string) {
|
|
|
|
l := icslog.GetIcsLog()
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "[HeartBeat] Conencted - %s", t.RemoteAddr().String())
|
|
|
|
fmt.Printf("[HeartBeat] Conencted - %s\n", t.RemoteAddr().String())
|
|
|
|
|
|
|
|
defer t.Close()
|
|
|
|
|
|
|
|
for {
|
|
|
|
buf, rlen, rerr := t.ReadS(0, bufend)
|
|
|
|
if rerr != nil {
|
|
|
|
fmt.Println("Reads Error!", rerr.GetError())
|
|
|
|
break
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "[%d] %s", rlen, string(buf))
|
|
|
|
fmt.Printf("[%d] %s\n", rlen, string(buf))
|
|
|
|
buf = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TCPConnHandlerSTT(t *icsnet.IcsTCPNet, bufend string) {
|
|
|
|
l := icslog.GetIcsLog()
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "[STT] Conencted - %s", t.RemoteAddr().String())
|
|
|
|
fmt.Printf("[STT] Conencted - %s\n", t.RemoteAddr().String())
|
|
|
|
|
|
|
|
defer t.Close()
|
|
|
|
|
|
|
|
for {
|
|
|
|
buf, rlen, rerr := t.ReadS(recorddata.MAX_CALLSIGNAL_PACKET_LEN, bufend)
|
|
|
|
if rerr != nil {
|
|
|
|
fmt.Println("Reads Error!", rerr.GetError())
|
|
|
|
break
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "STT - [%d] %s", rlen, string(buf))
|
|
|
|
fmt.Printf("[%d] %s\n", rlen, string(buf))
|
|
|
|
|
|
|
|
cs := readcallsignal.NewCallSignal(buf)
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "STT - call signal \n%v", cs)
|
|
|
|
buf = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TCPConnHandlerTTS(t *icsnet.IcsTCPNet, bufend string) {
|
|
|
|
l := icslog.GetIcsLog()
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "[TTS] Conencted - %s", t.RemoteAddr().String())
|
|
|
|
fmt.Printf("[TTS] Conencted - %s\n", t.RemoteAddr().String())
|
|
|
|
|
|
|
|
defer t.Close()
|
|
|
|
|
|
|
|
for {
|
|
|
|
buf, rlen, rerr := t.ReadS(0, bufend)
|
|
|
|
if rerr != nil {
|
|
|
|
fmt.Println("Reads Error!", rerr.GetError())
|
|
|
|
break
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "TTS - [%d] %s", rlen, string(buf))
|
|
|
|
fmt.Printf("[%d] %s\n", rlen, string(buf))
|
|
|
|
buf = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//processing bot command
|
|
|
|
func TCPConnHandlerCommand(t *icsnet.IcsTCPNet, bufend string) {
|
|
|
|
l := icslog.GetIcsLog()
|
|
|
|
//conf := icsconf.GetIcsConfig()
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "[Bot Command] Conencted - %s", t.RemoteAddr().String())
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "[Bot Command] Closed - %s", t.RemoteAddr().String())
|
|
|
|
t.Close()
|
|
|
|
}()
|
|
|
|
|
|
|
|
for {
|
|
|
|
buf, rlen, rerr := t.ReadS(81, bufend)
|
|
|
|
//buf, rlen, rerr := t.ReadS(0, bufend)
|
|
|
|
if rerr != nil {
|
|
|
|
if rerr.GetError() != io.EOF {
|
|
|
|
//fmt.Println("Reads Error!", rerr.GetError())
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "[Bot Command] Reads Error! - %s[%s]",
|
|
|
|
rerr.GetError(), string(buf))
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
aerr := rerr.GetError()
|
|
|
|
if aerr.Error() == "EOF" {
|
|
|
|
fmt.Println("Reads Error EOFFF!", rerr.GetError())
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
break
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "Recved Command - [%d] %s", rlen, string(buf))
|
|
|
|
//fmt.Printf("[%d] %s\n", rlen, string(buf))
|
|
|
|
|
|
|
|
cs := readcallsignal.NewCallSignal(buf)
|
|
|
|
if cs == nil {
|
|
|
|
l.Print(icslog.LOG_LEVEL_DEBUG2, -1, "[Call Signal] CallSignal Parsing Error!")
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
n := bytes.Index([]byte(cs.ChannelID), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
cs.ChannelID = string([]byte(cs.ChannelID)[:n])
|
|
|
|
}
|
|
|
|
n = bytes.Index([]byte(cs.Station), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
cs.Station = string([]byte(cs.Station)[:n])
|
|
|
|
}
|
|
|
|
n = bytes.Index([]byte(cs.AgentID), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
cs.AgentID = string([]byte(cs.AgentID)[:n])
|
|
|
|
}
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "Call Signal - [%d] chID: %s, SID: %s, Station: %s, AgentID: %s, EventType: %s, CustTel: %s, %d:%d",
|
|
|
|
len(buf),
|
|
|
|
cs.ChannelID,
|
|
|
|
cs.ServerID,
|
|
|
|
cs.Station,
|
|
|
|
cs.AgentID,
|
|
|
|
cs.EventType,
|
|
|
|
cs.CustID,
|
|
|
|
cs.StartTime,
|
|
|
|
cs.EndTime)
|
|
|
|
//fmt.Printf("345LINE [%d] %s\n", len(buf), string(buf))
|
|
|
|
|
|
|
|
if strings.Compare(cs.EventType, "S") == 0 { //START CALL
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, -1, "Call Started")
|
|
|
|
//alloc session with station
|
|
|
|
session, serr := icssessionmanager.AllocSession(cs.ChannelID, cs.ServerID, cs.Station, "", true)
|
|
|
|
if serr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Session Aloocation Failure. Check Licensed Session Number - %s", serr.GetError())
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//find agent conf
|
|
|
|
//if session.AgentConfig == nil {
|
|
|
|
agentConf := session.FindAgentConfig(cs.AgentID)
|
|
|
|
if agentConf == nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Could not find Agent Config - %s", cs.AgentID)
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
session.SetAgentConfig(agentConf)
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG, session.ID, "Set Agent Config - %s", cs.AgentID)
|
|
|
|
//}
|
|
|
|
|
|
|
|
//set tcp connection to session's for response
|
|
|
|
session.TcpConn = t
|
|
|
|
|
|
|
|
//listen voice port
|
|
|
|
vraddr := icsnet.NewNetAddrWithIPPort("0.0.0.0", session.AgentConfig.Port)
|
|
|
|
//vraddr := icsnet.NewNetAddrWithIPPort("0.0.0.0", conf.AgentConfig[session.ID].Port)
|
|
|
|
session.VoiceNeter = icsnet.NewUDP(&vraddr, nil)
|
|
|
|
lerr := session.VoiceNeter.Listen()
|
|
|
|
if lerr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_FATAL, session.ID, "Port[%s] Listen Failure - %s", vraddr, lerr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID, "Voice port listening - %s", vraddr)
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
url := fmt.Sprintf("http://%s:%d%s",
|
|
|
|
session.AgentConfig.BotConfig.IP,
|
|
|
|
session.AgentConfig.BotConfig.Port,
|
|
|
|
session.AgentConfig.BotConfig.URL)
|
|
|
|
icshttpclient.PostServiceInfo(url, session.AgentConfig.BotConfig.CustTel)
|
|
|
|
*/
|
|
|
|
|
|
|
|
//sesion start
|
|
|
|
session.Start()
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
//post event to the session
|
|
|
|
h := icsevent.NewEventH()
|
|
|
|
var evt *icsevent.Event
|
|
|
|
var evtErr *icserror.IcsError
|
|
|
|
if evt, evtErr = h.AllocEvent(cs); evtErr != nil {
|
|
|
|
//evtErr.Print()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Post SIP event[%d] to Session[%03d]", evt.ID, session.ID)
|
|
|
|
h.PostEvent(int(session.GetSessionID()), evt)
|
|
|
|
|
|
|
|
} else if strings.Compare(cs.EventType, "D") == 0 { //DTMF
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "DTMF Event - %s", cs.InOut)
|
|
|
|
|
|
|
|
//find session
|
|
|
|
session, serr := icssessionmanager.FindSession(cs)
|
|
|
|
if serr != nil || session == nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Finding Session Failure - %s", serr.GetError())
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
//post event to the session
|
|
|
|
h := icsevent.NewEventH()
|
|
|
|
var evt *icsevent.Event
|
|
|
|
var evtErr *icserror.IcsError
|
|
|
|
if evt, evtErr = h.AllocEvent(cs); evtErr != nil {
|
|
|
|
//evtErr.Print()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Post SIP event[%d] to Session[%03d]", evt.ID, session.ID)
|
|
|
|
h.PostEvent(int(session.GetSessionID()), evt)
|
|
|
|
} else if strings.Compare(cs.EventType, "E") == 0 { //END CALL
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, -1, "Call Ended")
|
|
|
|
|
|
|
|
//find session
|
|
|
|
session, serr := icssessionmanager.FindSession(cs)
|
|
|
|
if serr != nil || session == nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Finding Session Failure - %s", serr.GetError())
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//find agent conf
|
|
|
|
if session.AgentConfig == nil {
|
|
|
|
agentConf := session.FindAgentConfig(cs.AgentID)
|
|
|
|
if agentConf == nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Could not find Agent Config - %s", cs.AgentID)
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
session.SetAgentConfig(agentConf)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch session.AgentConfig.Action {
|
|
|
|
case "voicegateway":
|
|
|
|
url := fmt.Sprintf("http://%s:%d%s",
|
|
|
|
session.AgentConfig.BotConfig.IP,
|
|
|
|
session.AgentConfig.BotConfig.Port,
|
|
|
|
session.AgentConfig.BotConfig.URL2)
|
|
|
|
//remove null terminator
|
|
|
|
var custid string
|
|
|
|
n := bytes.Index([]byte(cs.CustID), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
custid = string([]byte(cs.CustID)[:n])
|
|
|
|
} else {
|
|
|
|
custid = cs.CustID
|
|
|
|
}
|
|
|
|
|
|
|
|
var sstation string
|
|
|
|
n = bytes.Index([]byte(cs.Station), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
sstation = string([]byte(cs.Station)[:n])
|
|
|
|
} else {
|
|
|
|
sstation = cs.Station
|
|
|
|
}
|
|
|
|
|
|
|
|
scallID := session.GetCallID()
|
|
|
|
botToken := session.GetBotToken()
|
|
|
|
|
|
|
|
//send hangup to bot
|
|
|
|
processResp := icshttpclient.PostProcess(url, "HANGUP", "", custid, "ICS_RCP", scallID, sstation, botToken, "")
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID, "CALL HANGUP - %+v", processResp)
|
|
|
|
}
|
|
|
|
|
|
|
|
//close voiceneter
|
|
|
|
verr := session.VoiceNeter.Close()
|
|
|
|
if verr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to close Voice port - %s", verr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, session.ID, "Closed Voice port")
|
|
|
|
}
|
|
|
|
|
|
|
|
//close session
|
|
|
|
session.Stop()
|
|
|
|
serr = session.RemoveSession()
|
|
|
|
if serr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "RemoveSession Error %s", serr.GetMessage())
|
|
|
|
}
|
|
|
|
buf = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//from VoiceCapture
|
|
|
|
func TCPConnHandlerCS(t *icsnet.IcsTCPNet, bufend string) {
|
|
|
|
l := icslog.GetIcsLog()
|
|
|
|
//conf := icsconf.GetIcsConfig()
|
|
|
|
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "[Call Signal] Connected - %s", t.RemoteAddr().String())
|
|
|
|
|
|
|
|
defer t.Close()
|
|
|
|
|
|
|
|
for {
|
|
|
|
buf, _, rerr := t.ReadS(recorddata.MAX_CALLSIGNAL_PACKET_LEN, bufend)
|
|
|
|
//buf, _, rerr := t.ReadS(61, bufend)
|
|
|
|
//buf, rlen, rerr := t.ReadS(0, bufend)
|
|
|
|
if rerr != nil {
|
|
|
|
if aerr := rerr.GetError(); aerr != io.EOF {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "[Call Signal] Reads Error! - %s", rerr.GetError())
|
|
|
|
}
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
cs := readcallsignal.NewCallSignal(buf)
|
|
|
|
if cs == nil {
|
|
|
|
l.Print(icslog.LOG_LEVEL_DEBUG2, -1, "[Call Signal] CallSignal Parsing Error!")
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
//var agentid string
|
|
|
|
n := bytes.Index([]byte(cs.CustID), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
cs.CustID = string([]byte(cs.CustID)[:n])
|
|
|
|
}
|
|
|
|
n = bytes.Index([]byte(cs.AgentID), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
cs.AgentID = string([]byte(cs.AgentID)[:n])
|
|
|
|
}
|
|
|
|
n = bytes.Index([]byte(cs.ChannelID), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
cs.ChannelID = string([]byte(cs.ChannelID)[:n])
|
|
|
|
}
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "Call Signal - [%d] chID: %s, SID: %s, Station: %s, AgentID: %s, EventType: %s, CustTel: %s, %d:%d",
|
|
|
|
len(buf),
|
|
|
|
cs.ChannelID,
|
|
|
|
cs.ServerID,
|
|
|
|
cs.Station,
|
|
|
|
cs.AgentID,
|
|
|
|
cs.EventType,
|
|
|
|
cs.CustID,
|
|
|
|
cs.StartTime,
|
|
|
|
cs.EndTime)
|
|
|
|
fmt.Printf("345LINE [%d] %s\n", len(buf), string(buf))
|
|
|
|
|
|
|
|
if strings.Compare(cs.EventType, "S") == 0 { //START CALL
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, -1, "Call Started")
|
|
|
|
session, serr := icssessionmanager.AllocSession(cs.ChannelID, cs.ServerID, cs.Station, "", true)
|
|
|
|
if serr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Session Aloocation Failure. Check Licensed Session Number - %s", serr.GetError())
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//find agent conf
|
|
|
|
//if session.AgentConfig == nil {
|
|
|
|
agentConf := session.FindAgentConfig(cs.AgentID)
|
|
|
|
if agentConf == nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Could not find Agent Config - %s", cs.AgentID)
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
session.SetAgentConfig(agentConf)
|
|
|
|
l.Printf(icslog.LOG_LEVEL_DEBUG, session.ID, "Set Agent Config - %s", cs.AgentID)
|
|
|
|
//}
|
|
|
|
|
|
|
|
//listen voice port
|
|
|
|
vraddr := icsnet.NewNetAddrWithIPPort("0.0.0.0", session.AgentConfig.Port)
|
|
|
|
session.VoiceNeter = icsnet.NewUDP(&vraddr, nil)
|
|
|
|
lerr := session.VoiceNeter.Listen()
|
|
|
|
if lerr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_FATAL, session.ID, "Port[%s] Listen Failure - %s", vraddr, lerr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID, "Voice port open - %s", vraddr)
|
|
|
|
}
|
|
|
|
|
|
|
|
//connect to websocket server
|
|
|
|
//TODO: error-handling!!
|
|
|
|
wshost := fmt.Sprintf("%s:%d", session.AgentConfig.WSConfig.IP, session.AgentConfig.WSConfig.Port)
|
|
|
|
wspath := fmt.Sprintf("/%s/%s/websocket", cs.Station, cs.Station) //cs.AgentID)
|
|
|
|
path := fmt.Sprintf("%s%s", session.AgentConfig.WSConfig.Path, wspath)
|
|
|
|
//path := fmt.Sprintf("%s%s", session.AgentConfig.WSConfig.Path, "/123/01234567/websocket")
|
|
|
|
//path := fmt.Sprintf("%s%s", conf.AgentConfig[session.ID].WSConfig.Path, "/123/01234567/websocket")
|
|
|
|
session.WSConn = icsws.NewWSClient(wshost, path)
|
|
|
|
wserr := session.WSConn.Connect()
|
|
|
|
if wserr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to connect Websocket server[%s/%s] - %s",
|
|
|
|
wshost, path, wserr.GetError())
|
|
|
|
} else {
|
|
|
|
//connect
|
|
|
|
imsg := icsws.NewIAP()
|
|
|
|
imsg.Connect()
|
|
|
|
ierr := session.WSConn.Write(imsg.String())
|
|
|
|
if ierr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to connect Websocket server[%s/%s] - %s",
|
|
|
|
wshost, path, ierr.GetError())
|
|
|
|
} else {
|
|
|
|
for iter := 0; iter < 3; iter++ {
|
|
|
|
connected, ierr := session.WSConn.Read()
|
|
|
|
if ierr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to connect Websocket server[%s/%s] - %s",
|
|
|
|
wshost, path, ierr.GetError())
|
|
|
|
} else {
|
|
|
|
if !strings.Contains(string(connected), "CONNECTED") {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to connect Websocket server[%s/%s]. Retry - %d",
|
|
|
|
wshost, path, iter)
|
|
|
|
continue
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID, "Connected Websocket server - %s",
|
|
|
|
string(connected))
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//subscribe
|
|
|
|
agentname := session.AgentConfig.Name
|
|
|
|
imsg.Subscribe(agentname)
|
|
|
|
ierr = session.WSConn.Write(imsg.String())
|
|
|
|
if ierr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to Subscribe - %s", ierr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, session.ID, "Subscribe Websocket")
|
|
|
|
}
|
|
|
|
//room in
|
|
|
|
imsg.RoomIn(agentname, agentname)
|
|
|
|
ierr = session.WSConn.Write(imsg.String())
|
|
|
|
if ierr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to sent Room-In - %s", ierr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID, "Sent Room-In to Websocket server [%s]", imsg.String())
|
|
|
|
}
|
|
|
|
//call start
|
|
|
|
var custid string
|
|
|
|
n := bytes.Index([]byte(cs.CustID), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
custid = string([]byte(cs.CustID)[:n])
|
|
|
|
} else {
|
|
|
|
custid = cs.CustID
|
|
|
|
}
|
|
|
|
imsg.CallStart(agentname, custid)
|
|
|
|
ierr = session.WSConn.Write(imsg.String())
|
|
|
|
if ierr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to sent Call Start - %s", ierr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID, "Sent Call start to Websocket server [%s]", imsg.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
session.Start()
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
h := icsevent.NewEventH()
|
|
|
|
var evt *icsevent.Event
|
|
|
|
var evtErr *icserror.IcsError
|
|
|
|
if evt, evtErr = h.AllocEvent(cs); evtErr != nil {
|
|
|
|
//evtErr.Print()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Post SIP event[%d] to Session[%03d]", evt.ID, session.ID)
|
|
|
|
h.PostEvent(int(session.GetSessionID()), evt)
|
|
|
|
|
|
|
|
buf = nil
|
|
|
|
} else if strings.Compare(cs.EventType, "E") == 0 { //END CALL
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, -1, "Call Ended")
|
|
|
|
session, serr := icssessionmanager.FindSession(cs)
|
|
|
|
if serr != nil || session == nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Finding Session Failure - %s", serr.GetError())
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//find agent conf
|
|
|
|
if session.AgentConfig == nil {
|
|
|
|
agentConf := session.FindAgentConfig(cs.AgentID)
|
|
|
|
if agentConf == nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Could not find Agent Config - %s", cs.AgentID)
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
session.SetAgentConfig(agentConf)
|
|
|
|
}
|
|
|
|
|
|
|
|
//close voiceneter
|
|
|
|
verr := session.VoiceNeter.Close()
|
|
|
|
if verr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failted to close Voice port - %s", verr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, session.ID, "Close Voice port")
|
|
|
|
}
|
|
|
|
|
|
|
|
agentname := session.AgentConfig.Name
|
|
|
|
//agentname := conf.AgentConfig[session.ID].Name
|
|
|
|
imsg := icsws.NewIAP()
|
|
|
|
//call end
|
|
|
|
var custid string
|
|
|
|
n := bytes.Index([]byte(cs.CustID), []byte{0})
|
|
|
|
if n != -1 {
|
|
|
|
custid = string([]byte(cs.CustID)[:n])
|
|
|
|
} else {
|
|
|
|
custid = cs.CustID
|
|
|
|
}
|
|
|
|
imsg.CallEnd(agentname, custid)
|
|
|
|
ierr := session.WSConn.Write(imsg.String())
|
|
|
|
if ierr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to sent Call End - %s", ierr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID, "Sent Call End to Websocket server [%s]", imsg.String())
|
|
|
|
}
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
//room out
|
|
|
|
imsg.RoomOut(agentname, agentname)
|
|
|
|
ierr = session.WSConn.Write(imsg.String())
|
|
|
|
if ierr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to sent Room-Out - %s", ierr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_INFO, session.ID, "Sent Room-Out to Websocket server [%s]", imsg.String())
|
|
|
|
}
|
|
|
|
//disconnect stomp
|
|
|
|
imsg.Disconnect()
|
|
|
|
ierr = session.WSConn.Write(imsg.String())
|
|
|
|
if ierr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to sent Disconnect - %s", ierr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, session.ID, "Sent Disconnect to Websocket server")
|
|
|
|
}
|
|
|
|
//close ws connection
|
|
|
|
verr = session.WSConn.Close()
|
|
|
|
if verr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "Failed to Close Websocket Connection - %s", verr.GetError())
|
|
|
|
} else {
|
|
|
|
l.Print(icslog.LOG_LEVEL_INFO, session.ID, "Close Websocket Connection")
|
|
|
|
}
|
|
|
|
|
|
|
|
session.Stop()
|
|
|
|
serr = session.RemoveSession()
|
|
|
|
if serr != nil {
|
|
|
|
l.Printf(icslog.LOG_LEVEL_ERROR, session.ID, "RemoveSession Error %s", serr.GetMessage())
|
|
|
|
}
|
|
|
|
buf = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|