diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..16ac9ce --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module gitlab.com/ics_cinnamon/voiceStatistics + +go 1.16 + +require ( + github.com/google/uuid v1.3.0 + github.com/satori/go.uuid v1.2.0 + github.com/stretchr/testify v1.7.0 + gitlab.com/ics_cinnamon/joy4 v1.0.26 + golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7f058b0 --- /dev/null +++ b/go.sum @@ -0,0 +1,22 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gitlab.com/ics_cinnamon/joy4 v1.0.26 h1:pW6grM/elr/Nv/ibbES3ChaREafCy2h950NZUTXVYVM= +gitlab.com/ics_cinnamon/joy4 v1.0.26/go.mod h1:LFfF6nA92KMmd/hrGEgQzkIsX/n+IlqCI8vbY8/NnNI= +gocv.io/x/gocv v0.27.0 h1:3X8I74ULsWHd4m7DQRv2Nqx5VkKscfUFnKgLNodiboI= +gocv.io/x/gocv v0.27.0/go.mod h1:n4LnYjykU6y9gn48yZf4eLCdtuSb77XxSkW6g0wGf/A= +golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI= +golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/icsapp/execsvc.go b/icsapp/execsvc.go new file mode 100644 index 0000000..0a83d25 --- /dev/null +++ b/icsapp/execsvc.go @@ -0,0 +1,70 @@ +package icsapp + +import ( + "time" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icslog" + "gitlab.com/ics_cinnamon/voiceStatistics/icsnet" + "gitlab.com/ics_cinnamon/voiceStatistics/icsstat" + "gitlab.com/ics_cinnamon/voiceStatistics/icssvc" +) + +const ( + LINEEND1 = "\r\n" + LINEEND2 = "EOM" +) + +type IcsExec struct { + service *icssvc.IcsService + config *icsconf.IcsConfig + hbNet *icsnet.IcsTCPNet + //pcap icspcap.IcsPcap +} + +func Init(conf *icsconf.IcsConfig) (e *IcsExec) { + e = &IcsExec{} + e.service = icssvc.GetServiceStatus() + e.config = conf + //e.pcap = icspcap.New() + + return e +} + +func (exe IcsExec) Execute() *icserror.IcsError { + l := icslog.GetIcsLog() + + l.Printf(icslog.LOG_LEVEL_FATAL, -1, "11111") + for !exe.service.GetExit() { + for exe.service.GetStop() { + time.Sleep(time.Millisecond) + } + + ///////////////////////////////////////////////////////////////////// + //start statistic tcp + cmdDone := make(chan *icserror.IcsError) + go func() { + cmdErr := icsstat.ListenStatMNG() + if cmdErr != nil { + cmdDone <- cmdErr + return + } + //defer sm.Close() + + //cmdDone <- nil + }() + ///////////////////////////////////////////////////////////////////// + + select { + case err := <-cmdDone: + l.Printf(icslog.LOG_LEVEL_INFO, -1, "Closed Stat TCP Connection: %s", err) + if err != nil { + //err.Print() + return err + } + } + } + + return nil +} diff --git a/icsconf/icsconf.go b/icsconf/icsconf.go new file mode 100644 index 0000000..51c4f22 --- /dev/null +++ b/icsconf/icsconf.go @@ -0,0 +1,407 @@ +package icsconf + +import ( + "encoding/xml" + "fmt" + "os" + "strings" + "sync" + + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" +) + +type IcsConfig struct { + XMLName xml.Name `xml:"ICSVS"` + Version string `xml:"version,attr"` + InfoConfig InfoConfig `xml:"INFO"` + LogConfig LogConfig `xml:"LOG"` + Linger int `xml:"LINGER"` + Target Target `xml:"TARGET"` + HomeDir string +} + +type InfoConfig struct { + Product string `xml:"PRODUCT"` + TenentID string `xml:"TENENTID"` + ServerID int `xml:"SERVERID"` + ServerIP string `xml:"SERVERIP"` +} + +type Target struct { + Transport string `xml:"transport,attr"` + TargetPort int `xml:"port,attr"` +} + +type LogConfig struct { + Path string `xml:"PATH"` + Disklimit int `xml:"DISKLIMIT"` + Level string `xml:"LEVEL"` + Output string `xml:"OUTPUT"` + RotateConfig RotateConfig `xml:"ROTATE"` + DelConfig DelConfig `xml:"DELPERIOD"` + HomeDir string +} + +type DelConfig struct { + DelDay int `xml:"day,attr"` + DelHour int `xml:"hour,attr"` +} + +type RotateConfig struct { + Size string `xml:"size,attr"` + Num string `xml:"num,attr"` + YesNo string `xml:"yesno,attr"` +} + +var gIcsConfig *IcsConfig +var onceConfig sync.Once + +func OpenConfig(ConfigFileName string, homeDir string) (*IcsConfig, *icserror.IcsError) { + var gerr *icserror.IcsError = nil + + onceConfig.Do(func() { + fi, err := os.Open(ConfigFileName) + if err != nil { + icserror.ICSERRCONFOpenFile.SetError(err) + gerr = icserror.ICSERRCONFOpenFile + return + } + defer fi.Close() + + FI, _ := os.Stat(ConfigFileName) + FileLength := FI.Size() + + configdata := make([]byte, FileLength) + cnt, err := fi.Read(configdata) + if cnt == 0 || err != nil { + icserror.ICSERRCONFFileNotFound.SetError(err) + gerr = icserror.ICSERRCONFFileNotFound + return + } + + gIcsConfig = &IcsConfig{} + gIcsConfig.HomeDir = homeDir + + err = xml.Unmarshal([]byte(configdata), gIcsConfig) + if err != nil { + icserror.ICSERRCONFUnmarshal.SetError(err) + gerr = icserror.ICSERRCONFUnmarshal + gIcsConfig = nil + return + } + + if !strings.HasPrefix(gIcsConfig.LogConfig.Path, "/") { + gIcsConfig.LogConfig.Path = fmt.Sprintf("%s/%s", homeDir, gIcsConfig.LogConfig.Path) + } + //default setting + if gIcsConfig.LogConfig.DelConfig.DelDay == 0 { + gIcsConfig.LogConfig.DelConfig.DelHour = 90 + } + if gIcsConfig.LogConfig.DelConfig.DelHour == 0 { + gIcsConfig.LogConfig.DelConfig.DelHour = 2 + } + + gIcsConfig.LogConfig.HomeDir = homeDir + }) + + if gerr != nil { + return nil, gerr + } + + return gIcsConfig, nil +} + +func ReloadConfig(ConfigFileName string, homeDir string) (*IcsConfig, *icserror.IcsError) { + fi, err := os.Open(ConfigFileName) + if err != nil { + icserror.ICSERRCONFOpenFile.SetError(err) + return nil, icserror.ICSERRCONFOpenFile + } + defer fi.Close() + + FI, _ := os.Stat(ConfigFileName) + FileLength := FI.Size() + + configdata := make([]byte, FileLength) + cnt, err := fi.Read(configdata) + if cnt == 0 || err != nil { + icserror.ICSERRCONFFileNotFound.SetError(err) + return nil, icserror.ICSERRCONFFileNotFound + } + + gIcsConfig = &IcsConfig{} + gIcsConfig.HomeDir = homeDir + + err = xml.Unmarshal([]byte(configdata), gIcsConfig) + if err != nil { + icserror.ICSERRCONFUnmarshal.SetError(err) + return nil, icserror.ICSERRCONFUnmarshal + } + + if !strings.HasPrefix(gIcsConfig.LogConfig.Path, "/") { + gIcsConfig.LogConfig.Path = fmt.Sprintf("%s/%s", homeDir, gIcsConfig.LogConfig.Path) + } + //default setting + if gIcsConfig.LogConfig.DelConfig.DelDay == 0 { + gIcsConfig.LogConfig.DelConfig.DelHour = 90 + } + if gIcsConfig.LogConfig.DelConfig.DelHour == 0 { + gIcsConfig.LogConfig.DelConfig.DelHour = 2 + } + + gIcsConfig.LogConfig.HomeDir = homeDir + + return gIcsConfig, nil +} + +func (c IcsConfig) GetHomeDir() string { + return c.HomeDir +} + +func (c IcsConfig) GetChannelID() string { + return c.InfoConfig.TenentID +} + +func (c IcsConfig) GetServerID() int { + return c.InfoConfig.ServerID +} + +//from LogConfig struct +func (c LogConfig) GetHomeDir() string { + return c.HomeDir +} + +func (c *IcsConfig) SetHomeDir(homeDir string) { + c.HomeDir = homeDir +} + +func GetIcsConfig() *IcsConfig { + return gIcsConfig +} + +func (c IcsConfig) ShowConfig() string { + fmt.Printf("Log Level : %s\n", c.LogConfig.Level) + fmt.Printf("Log Path : %s\n", c.LogConfig.Path) + fmt.Printf("Log Disk Space Size : %dMB\n", c.LogConfig.Disklimit) + fmt.Printf("Log Del Day : %d\n", c.LogConfig.DelConfig.DelDay) + fmt.Printf("Log Del Hour : %d\n", c.LogConfig.DelConfig.DelHour) + fmt.Printf("Log Output : %s\n", c.LogConfig.Output) + fmt.Printf("Log Rotate : %s\n", c.LogConfig.RotateConfig.YesNo) + fmt.Printf("Log Rotate File Size : %sMB\n", c.LogConfig.RotateConfig.Size) + fmt.Printf("Log Rotate File Number : %s\n\n", c.LogConfig.RotateConfig.Num) + fmt.Printf("Log Del Day : %d\n", c.LogConfig.DelConfig.DelDay) + fmt.Printf("Log Del Hour : %d\n", c.LogConfig.DelConfig.DelHour) + /* + for iter := 0; iter < len(c.AgentConfig); iter++ { + fmt.Printf("==========================\n") + fmt.Printf("Agent Name: %s, Use? %s\n", c.AgentConfig[iter].Name, c.AgentConfig[iter].Value) + fmt.Printf("Agent Media media: %s\n", c.AgentConfig[iter].MediaConfig.Media) + fmt.Printf("Agent Media Port: %d\n", c.AgentConfig[iter].MediaConfig.Port) + fmt.Printf("Agent Media Format: %s\n", c.AgentConfig[iter].MediaConfig.Format) + fmt.Printf("Register value: %s\n", c.AgentConfig[iter].RegisterConfig.RegisterValue) + fmt.Printf("Register Transport: %s\n", c.AgentConfig[iter].RegisterConfig.RegisterTransport) + fmt.Printf("Register Expire: %d\n", c.AgentConfig[iter].RegisterConfig.RegisterExpire) + fmt.Printf("Register Username: %s\n", c.AgentConfig[iter].RegisterConfig.RegisterUserName) + fmt.Printf("Options Use? %s\n", c.AgentConfig[iter].OptionsConfig.OptionsValue) + fmt.Printf("Options Interval: %d\n\n", c.AgentConfig[iter].OptionsConfig.OptionsInterval) + } + */ + + /* + confmsg += fmt.Sprintf("iComsys Voice Agent Address : %s[%d:%d]\n", + c.VoiceAgentConfig.AgentAddr.VoiceAgentIP, c.VoiceAgentConfig.AgentAddr.CallSignalPort, c.VoiceAgentConfig.AgentAddr.VoicePort) + */ + confmsg := fmt.Sprintf("Log Level : %s\n", c.LogConfig.Level) + confmsg += fmt.Sprintf("Log Path : %s\n", c.LogConfig.Path) + confmsg += fmt.Sprintf("Log Disk Space Size : %dMB\n", c.LogConfig.Disklimit) + confmsg += fmt.Sprintf("Log Del Day : %d\n", c.LogConfig.DelConfig.DelDay) + confmsg += fmt.Sprintf("Log Del Hour : %d\n", c.LogConfig.DelConfig.DelHour) + confmsg += fmt.Sprintf("Log Output : %s\n", c.LogConfig.Output) + confmsg += fmt.Sprintf("Log Rotate : %s\n", c.LogConfig.RotateConfig.YesNo) + confmsg += fmt.Sprintf("Log Rotate File Size : %sMB\n", c.LogConfig.RotateConfig.Size) + confmsg += fmt.Sprintf("Log Rotate File Number : %s\n\n", c.LogConfig.RotateConfig.Num) + + return confmsg +} + +////////////////////////////////////////// +/////////////// simulator //////////////// +////////////////////////////////////////// + +type SimConfig struct { + XMLName xml.Name `xml:"SIMVC"` + Version string `xml:"version,attr"` + IsCaller string `xml:"ISCALLER"` + Repeat int `xml:"REPEAT"` + Channels int `xml:"CHANNELS"` + TargetPhoneConfig TargetPhoneConfig `xml:"TARGET"` + SimPhoneConfig SimPhoneConfig `xml:"SIM"` + InOut string `xml:"INOUT"` + LogConfig LogConfig `xml:"LOG"` + RegiCount int `xml:"REGICOUNT"` + MediaConfig []SimMediaConfig `xml:"MEDIA"` + HomeDir string +} + +type TargetPhoneConfig struct { + TargetIP string `xml:"ip,attr"` + TSIPPort int `xml:"sipport,attr"` + TRTPPort int `xml:"rtpport,attr"` +} + +type SimPhoneConfig struct { + MYIP string `xml:"myip,attr"` + SIPPort int `xml:"sipport,attr"` + RTPPort int `xml:"rtpport,attr"` +} + +type SimMediaConfig struct { + Media string `xml:"m,attr"` + Port int `xml:"port,attr"` + Format string `xml:"format,attr"` +} + +type SimScenarioConfig struct { + XMLName xml.Name `xml:"SIMSCEN"` + Version string `xml:"version,attr"` + ScenarioCount int `xml:"SCENARIOCOUNT"` + SipOrder SipOrder `xml:"ORDER"` +} + +type SipOrder struct { + Order []string `xml:"METHOD"` + StopTime int `xml:"STOPTIME"` +} + +func OpenSimConfig(ConfigFileName string, homeDir string) (*SimConfig, *icserror.IcsError) { + fi, err := os.Open(ConfigFileName) + if err != nil { + icserror.ICSERRCONFOpenFile.SetError(err) + return nil, icserror.ICSERRCONFOpenFile + } + defer fi.Close() + + FI, _ := os.Stat(ConfigFileName) + FileLength := FI.Size() + + configdata := make([]byte, FileLength) + cnt, err := fi.Read(configdata) + if cnt == 0 || err != nil { + icserror.ICSERRCONFFileNotFound.SetError(err) + return nil, icserror.ICSERRCONFFileNotFound + } + + conf := SimConfig{} + conf.HomeDir = homeDir + + err = xml.Unmarshal([]byte(configdata), &conf) + if err != nil { + icserror.ICSERRCONFUnmarshal.SetError(err) + return nil, icserror.ICSERRCONFUnmarshal + } + + /* + fmt.Printf("Configuration> xml name: %s, version: %s\n", conf.XMLName.Local, conf.Version) + fmt.Println(conf.LicenseConfig) + fmt.Println(conf.LogConfig) + fmt.Println(conf.LogConfig.RotateConfig) + fmt.Println(conf.CaptureConfig) + */ + + conf.LogConfig.HomeDir = homeDir + + gSimConfig = &conf + + return &conf, nil +} + +func OpenSimScenarioConfig(ConfigFileName string, homeDir string) (*SimScenarioConfig, *icserror.IcsError) { + fi, err := os.Open(ConfigFileName) + if err != nil { + icserror.ICSERRCONFOpenFile.SetError(err) + return nil, icserror.ICSERRCONFOpenFile + } + defer fi.Close() + + FI, _ := os.Stat(ConfigFileName) + FileLength := FI.Size() + + configdata := make([]byte, FileLength) + cnt, err := fi.Read(configdata) + if cnt == 0 || err != nil { + icserror.ICSERRCONFFileNotFound.SetError(err) + return nil, icserror.ICSERRCONFFileNotFound + } + + SimScenarioConf := SimScenarioConfig{} + + err = xml.Unmarshal([]byte(configdata), &SimScenarioConf) + if err != nil { + icserror.ICSERRCONFUnmarshal.SetError(err) + return nil, icserror.ICSERRCONFUnmarshal + } + + fmt.Println() + + gSimScenarioConfig = &SimScenarioConf + return &SimScenarioConf, nil +} + +func (c SimConfig) GetSimChannels() int { + return c.Channels +} + +func (c SimConfig) GetSimTargetIP() string { + return c.TargetPhoneConfig.TargetIP +} + +func (c SimConfig) GetSimTargetPort() int { + return c.TargetPhoneConfig.TSIPPort +} + +func (c SimConfig) ShowConfig() string { + fmt.Printf("Home Path : %s\n", c.HomeDir) + fmt.Printf("INOUT : %s\n", c.InOut) + fmt.Printf("Channel number : %d\n", c.Channels) + fmt.Printf("Repeat number : %d\n", c.Repeat) + fmt.Printf("iComsys SIM Phone Address : %s\n", c.SimPhoneConfig.MYIP) + fmt.Printf("iComsys Target Phone Address : %s\n", c.GetSimTargetIP()) + fmt.Printf("Log Level : %s\n", c.LogConfig.Level) + fmt.Printf("Log Path : %s\n", c.LogConfig.Path) + fmt.Printf("Log Disk Space Limitation : %dMB\n", c.LogConfig.Disklimit) + fmt.Printf("Log Output : %s\n", c.LogConfig.Output) + fmt.Printf("Log Rotate : %s\n", c.LogConfig.RotateConfig.YesNo) + fmt.Printf("Log Rotate File Size : %s\n", c.LogConfig.RotateConfig.Size) + fmt.Printf("Log Rotate File Number : %s\n", c.LogConfig.RotateConfig.Num) + fmt.Printf("SIP Port: %d\n", c.SimPhoneConfig.SIPPort) + fmt.Printf("RTP Port: %d\n", c.SimPhoneConfig.RTPPort) + + confmsg := "" + confmsg += fmt.Sprintf("Home Path : %s\n", c.HomeDir) + confmsg += fmt.Sprintf("Caller : %s\n", c.IsCaller) + confmsg += fmt.Sprintf("Channel number : %d\n", c.Channels) + confmsg += fmt.Sprintf("iComsys SIM Phone Address : %s\n", c.SimPhoneConfig.MYIP) + confmsg += fmt.Sprintf("iComsys Target Phone Address : %s\n", c.GetSimTargetIP()) + confmsg += fmt.Sprintf("Log Level : %s\n", c.LogConfig.Level) + confmsg += fmt.Sprintf("Log Path : %s\n", c.LogConfig.Path) + confmsg += fmt.Sprintf("Log Disk Space Limitation : %dMB\n", c.LogConfig.Disklimit) + confmsg += fmt.Sprintf("Log Output : %s\n", c.LogConfig.Output) + confmsg += fmt.Sprintf("Log Rotate : %s\n\n", c.LogConfig.RotateConfig.YesNo) + confmsg += fmt.Sprintf("Log Rotate File Size : %s\n", c.LogConfig.RotateConfig.Size) + confmsg += fmt.Sprintf("Log Rotate File Number : %s\n", c.LogConfig.RotateConfig.Num) + confmsg += fmt.Sprintf("SIP Port: %d\n", c.SimPhoneConfig.SIPPort) + confmsg += fmt.Sprintf("RTP Port: %d\n\n", c.SimPhoneConfig.RTPPort) + + return confmsg +} + +var gSimConfig *SimConfig +var gSimScenarioConfig *SimScenarioConfig + +func GetSimConfig() *SimConfig { + return gSimConfig +} + +func GetSimScenarioConfig() *SimScenarioConfig { + return gSimScenarioConfig +} diff --git a/icserror/icserror.go b/icserror/icserror.go new file mode 100644 index 0000000..4594fdb --- /dev/null +++ b/icserror/icserror.go @@ -0,0 +1,66 @@ +//error system package +package icserror + +import ( + "errors" + "fmt" + "runtime" + "strings" +) + +type IcsError struct { + code interface{} + message string + err error +} + +func GetModName() string { + return "icserror" +} + +func NewIcsError(errString string, code interface{}) *IcsError { + var err IcsError + err.err = errors.New(errString) + err.code = code + err.message = errString + + return &err +} + +func (e IcsError) Print() { + fmt.Printf("Code: %v, Message: %s, Error: %v\n", e.code, e.message, e.err) +} + +func (e IcsError) PrintWithCaller(depth int) { + errstr := fmt.Sprintf("Code: %v, Message: %s, Error: %s", e.code, e.message, e.err) + funcname, file, line, ok := runtime.Caller(depth) + if ok { + files := strings.Split(file, "/") + fileslen := len(files) + func1 := runtime.FuncForPC(funcname).Name() + funcs := strings.Split(func1, "/") + funcslen := len(funcs) + + fmt.Printf("[%s:%d %s] %s\n", files[fileslen-1], line, funcs[funcslen-1], errstr) + } +} + +func (e IcsError) Equal(i *IcsError) bool { + return e.code == i.code +} + +func (e *IcsError) SetError(baseError error) { + e.err = baseError +} + +func (e *IcsError) GetCode() interface{} { + return e.code +} + +func (e *IcsError) GetMessage() string { + return e.message +} + +func (e *IcsError) GetError() error { + return e.err +} diff --git a/icserror/icserror_test.go b/icserror/icserror_test.go new file mode 100644 index 0000000..6399ebc --- /dev/null +++ b/icserror/icserror_test.go @@ -0,0 +1,18 @@ +package icserror + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetModName(t *testing.T) { + got := GetModName() + assert.Equal(t, "icserror", got, "not expected value") + + g1 := NewIcsError("Test", 0) + g2 := NewIcsError("Test", 0) + assert.Equal(t, g1, g2, "not expected value") + + assert.Equal(t, g1.Equal(g2), true, "not expected value") +} diff --git a/icserror/icserrordef.go b/icserror/icserrordef.go new file mode 100644 index 0000000..8c968a0 --- /dev/null +++ b/icserror/icserrordef.go @@ -0,0 +1,205 @@ +package icserror + +const ( + ICS_ERROR_COMMON = iota + ICS_ERROR_CONFIG = ICS_ERROR_COMMON + 1000 + ICS_ERROR_SVC = ICS_ERROR_COMMON + 2000 + ICS_ERROR_UTIL = ICS_ERROR_COMMON + 2500 + ICS_ERROR_SIP_PROCESSOR = ICS_ERROR_COMMON + 3000 + ICS_ERROR_NET = ICS_ERROR_COMMON + 4000 + ICS_ERROR_RECORDDATA = ICS_ERROR_COMMON + 4500 + ICS_ERROR_SIP_PARSER = ICS_ERROR_COMMON + 5000 + ICS_ERROR_SDP_PARSER = ICS_ERROR_COMMON + 5500 + ICS_ERROR_RTP_PARSER = ICS_ERROR_COMMON + 6000 + ICS_ERROR_DTMF = ICS_ERROR_COMMON + 6500 + ICS_ERROR_CONV = ICS_ERROR_COMMON + 7000 + ICS_ERROR_SESS = ICS_ERROR_COMMON + 8000 + ICS_ERROR_EVENT = ICS_ERROR_COMMON + 9000 +) + +//common error +const ( + ICSOK = iota + ICS_ERROR_COMMON + ICSFALSE + ICS_ERROR_NOTFOUND_HOME + ICS_ERROR_INVALID_PARAM + ICS_ERROR_FILE_OPEN + ICS_ERROR_MAKE_DIR + ICS_ERROR_STRING_CONV + ICS_ERROR_DAEMONIZE + ICS_ERROR_UNKNOWN +) + +var ( + ICSERRTest = NewIcsError("This Is Error Test", ICSOK) + ICSERRNotFoundHome = NewIcsError("Not found HOME Directory", ICS_ERROR_NOTFOUND_HOME) + ICSERRInvalidParam = NewIcsError("Invalid Parameter", ICS_ERROR_INVALID_PARAM) + ICSERRFileOpen = NewIcsError("File Open Error", ICS_ERROR_FILE_OPEN) + ICSERRMakeDir = NewIcsError("File Open Error", ICS_ERROR_MAKE_DIR) + ICSERRStrConv = NewIcsError("Atoi Error", ICS_ERROR_STRING_CONV) + ICSERRDeamonize = NewIcsError("Process Deamonize Error", ICS_ERROR_DAEMONIZE) + ICSERRUnkown = NewIcsError("Unknown Error", ICS_ERROR_UNKNOWN) +) + +//config error +const ( + ICS_ERROR_CONFIG_FILE_NOTFOUND = iota + ICS_ERROR_CONFIG + ICS_ERROR_CONFIG_OPEN_FILE + ICS_ERROR_CONFIG_UNMARSHAL +) + +var ( + ICSERRCONFFileNotFound = NewIcsError("icsconfig: Not Found The Config File ", ICS_ERROR_CONFIG_FILE_NOTFOUND) + ICSERRCONFOpenFile = NewIcsError("icsconfig: Configuration File Open Error", ICS_ERROR_CONFIG_OPEN_FILE) + ICSERRCONFUnmarshal = NewIcsError("icsconfig: Config File Unmarshal Error", ICS_ERROR_CONFIG_UNMARSHAL) +) + +//service error +const ( + ICS_ERROR_SVC_WRONG_TIME = iota + ICS_ERROR_SVC + ICS_ERROR_SVC_NOT_INIT +) + +var ( + ICSERRSVCTime = NewIcsError("icsservice: Wrong time", ICS_ERROR_SVC_WRONG_TIME) + ICSERRSVCInit = NewIcsError("icsapp: Not init service", ICS_ERROR_SVC_NOT_INIT) +) + +//util error +const ( + ICS_ERROR_UTIL_DISK_FULL = iota + ICS_ERROR_UTIL +) + +var ( + ICSERRUTILDiskFull = NewIcsError("icsutil: Disk Full", ICS_ERROR_UTIL_DISK_FULL) +) + +/* +//sip processor error +const ( + ICS_ERROR_PCAP_OPENLIVE = iota + ICS_ERROR_PCAP + ICS_ERROR_PCAP_SETFILTER + ICS_ERROR_PCAP_EOF +) + +var ( + ICSERRPCAPOpenLive = NewIcsError("icspcap: OpenLive Error", ICS_ERROR_PCAP_OPENLIVE) + ICSERRPCAPSetFilter = NewIcsError("icspcap: Set filter Error", ICS_ERROR_PCAP_SETFILTER) + ICSERRPCAPEOF = NewIcsError("icspcap: Packet EOF", ICS_ERROR_PCAP_EOF) +) +*/ + +//net error +const ( + ICS_ERROR_NET_RESOLVEADDR = iota + ICS_ERROR_NET + ICS_ERROR_NET_LISTEN + ICS_ERROR_NET_CONNECT + ICS_ERROR_NET_NOT_CONNECTED + ICS_ERROR_NET_CLOSE + ICS_ERROR_NET_WRITE + ICS_ERROR_NET_READ + ICS_ERROR_NET_ACCEPT + ICS_ERROR_NET_NOT_FOUND_IF + ICS_ERROR_NET_GET_ADDR +) + +var ( + ICSERRNETResolveAddrError = NewIcsError("icsnet: Resolve Address Error", ICS_ERROR_NET_RESOLVEADDR) + ICSERRNETListenError = NewIcsError("icsnet: Listen Error", ICS_ERROR_NET_LISTEN) + ICSERRNETConnectError = NewIcsError("icsnet: Connect Error", ICS_ERROR_NET_CONNECT) + ICSERRNETNotConnectError = NewIcsError("icsnet: Connection is not completed yet", ICS_ERROR_NET_NOT_CONNECTED) + ICSERRNETCloseError = NewIcsError("icsnet: Close Error", ICS_ERROR_NET_CLOSE) + ICSERRNETWriteError = NewIcsError("icsnet: Write Error", ICS_ERROR_NET_WRITE) + ICSERRNETReadError = NewIcsError("icsnet: Read Error", ICS_ERROR_NET_READ) + ICSERRNETAcceptError = NewIcsError("icsnet: Accept Error", ICS_ERROR_NET_ACCEPT) + ICSERRNETNotFoundIF = NewIcsError("icsnet: Not Found Interface", ICS_ERROR_NET_NOT_FOUND_IF) + ICSERRNETGetAddr = NewIcsError("icsnet: Could Not Get Address", ICS_ERROR_NET_GET_ADDR) +) + +//recorddata error +const ( + ICS_ERROR_RECORDDATA_CALLSIGNAL_PARSING = iota + ICS_ERROR_RECORDDATA +) + +var ( + ICSERRRECORDDATAParsing = NewIcsError("recorddata: Parsing Error", ICS_ERROR_RECORDDATA_CALLSIGNAL_PARSING) +) + +//sip parsing error +var ( + ICSERRSIPHeader = NewIcsError("icssip: Header format Error", ICS_ERROR_SIP_PARSER) + ICSERRINVITERequired = NewIcsError("icssip: INVITE Method required SDP", ICS_ERROR_SIP_PARSER) + ICSERR200OKRequired = NewIcsError("icssip: 200 OK Method required SDP", ICS_ERROR_SIP_PARSER) +) + +//sdp parsing error +var ( + ICSERRSDPParser = NewIcsError("icssdp: Data parser Error", ICS_ERROR_SDP_PARSER) + ICSERRNotFoundSdpMedia = NewIcsError("icssdp: Not Found SDP Media audio tag", ICS_ERROR_SDP_PARSER) + ICSERRSDPAudiotagPortValue = NewIcsError("icssdp: SDP Media audio tag port is not numeric", ICS_ERROR_SDP_PARSER) +) + +//rtp parser error +const ( + ICS_ERROR_RTP_NO = iota + ICS_ERROR_RTP_PARSER +) + +var ( + ICSERRRTPNo = NewIcsError("icsrtp: This packet may not be RTP", ICS_ERROR_RTP_NO) +) + +//dtmf parser error +const ( + ICS_ERROR_DTMF_OK = iota + ICS_ERROR_DTMF + ICS_ERROR_DTMF_CONT + ICS_ERROR_DTMF_FAIL +) + +var ( + ICSERRDTMFOK = NewIcsError("icsdtmf: Detected DTMF", ICS_ERROR_DTMF_OK) + ICSERRDTMFCont = NewIcsError("icsdtmf: Processing detect", ICS_ERROR_DTMF_CONT) + ICSERRDTMFFail = NewIcsError("icsdtmf: Failed detection DTMF", ICS_ERROR_DTMF_FAIL) +) + +//media converter error +const ( + ICS_ERROR_CONV_NOT_SUPPORTED_CODEC = iota + ICS_ERROR_CONV + ICS_ERROR_CONV_DECODE + ICS_ERROR_CONV_ENCODE +) + +var ( + ICSERRCONVNotSupportedCodec = NewIcsError("icsmediaconv: Not Supported codec", ICS_ERROR_CONV_NOT_SUPPORTED_CODEC) + ICSERRCONVDecodeFail = NewIcsError("icsmediaconv: Decoding Fail", ICS_ERROR_CONV_DECODE) + ICSERRCONVEncodeFail = NewIcsError("icsmediaconv: Encoding Fail", ICS_ERROR_CONV_ENCODE) +) + +//session error +const ( + ICS_ERROR_SESS_NOT_FOUND_SESSION = iota + ICS_ERROR_SESS + ICS_ERROR_SESS_SESSION_MAX_IDLE + ICS_ERROR_SESS_SESSION_NUM_EXCEED +) + +var ( + ICSERRSESSNotFoundSession = NewIcsError("icssessionmanager: Not Found Session", ICS_ERROR_SESS_NOT_FOUND_SESSION) + ICSERRSESSMaxSessionIdle = NewIcsError("icssessionmanager: Exceeded Session Max Idling Time", ICS_ERROR_SESS_SESSION_MAX_IDLE) + ICSERRSESSMaxSessionNumber = NewIcsError("icssessionmanager: Licensed Channel Number Exceeded ", ICS_ERROR_SESS_SESSION_NUM_EXCEED) +) + +//event error +const ( + ICS_ERROR_EVT_ALLOC = iota + ICS_ERROR_EVENT + ICS_ERROR_EVT_REMOVE + ICS_ERROR_EVT_POST + ICS_ERROR_EVT_NOT_INITIALIZE + ICS_ERROR_EVT_UNKNOWN +) + +var ( + ICSERREVTAlloc = NewIcsError("icsevent: Event Allocation Error", ICS_ERROR_EVT_ALLOC) + ICSERREVTRemove = NewIcsError("icsevent: Event Remove Error", ICS_ERROR_EVT_REMOVE) + ICSERREVTPost = NewIcsError("icsevent: Event Post Error", ICS_ERROR_EVT_POST) + ICSERREVTNotInit = NewIcsError("icsevent: Event System Not Initialized", ICS_ERROR_EVT_NOT_INITIALIZE) + ICSERREVTUnkown = NewIcsError("icsevent: Unkown Error", ICS_ERROR_EVT_UNKNOWN) +) diff --git a/icsevent/datastruct.go b/icsevent/datastruct.go new file mode 100644 index 0000000..8dab0c3 --- /dev/null +++ b/icsevent/datastruct.go @@ -0,0 +1,90 @@ +package icsevent + +import ( + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icslog" +) + +//////////////////////////////////////////////////////////////////// +// round robin data structure +type RRData struct { + data interface{} + //data *interface{} + + tail *RRData +} + +func NewRRData() *RRData { + r := &RRData{ + tail: nil, + } + return r +} + +func Push(first *RRData, data interface{}) *icserror.IcsError { + if first == nil { + return icserror.ICSERRInvalidParam + } + + ret := NewRRData() + ret.data = data + var tmp *RRData + + //search end point + cnt := 0 + for tmp = first; tmp.tail != nil; tmp = tmp.tail { + cnt++ + } + + //assign data to end point + tmp.tail = ret + + return nil +} + +func Pop(first *RRData) (*RRData, interface{}, *icserror.IcsError) { + if first == nil { + return nil, nil, icserror.ICSERRInvalidParam + } + + //l := icslog.GetIcsLog() + + ftail := first.tail + + ret := first.tail + + if ret != nil && ret.data != nil { + } else { + return first, nil, nil + } + first = ftail + + return first, ret.data, nil +} + +func (r *RRData) GetData() interface{} { + return r.data +} + +func GetLength(first *RRData) (int, *icserror.IcsError) { + if first == nil { + return -1, icserror.ICSERRInvalidParam + } + + l := icslog.GetIcsLog() + var iter int = 0 + for tmp := first; tmp != nil && tmp.tail != nil; tmp = tmp.tail { + var id int + h := NewEventH() + switch v := tmp.data.(type) { + case int: + id = v + } + p := h.getEvt(id) + l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "GetLength(%d)>%d-%v tmp>%p-%p", iter, id, p, tmp, tmp.tail) + + iter++ + } + + return iter, nil +} diff --git a/icsevent/datastruct_test.go b/icsevent/datastruct_test.go new file mode 100644 index 0000000..3fec911 --- /dev/null +++ b/icsevent/datastruct_test.go @@ -0,0 +1,55 @@ +package icsevent + +import ( + "fmt" + "testing" + + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" +) + +func TestDataStruct(t *testing.T) { + var header *RRData + header = NewRRData() + + for i := 0; i < 128; i++ { + err := Push(header, i) + if err != nil { + err.Print() + break + } + } + + for i := 0; i < 128; i++ { + var data interface{} + var err *icserror.IcsError + //fmt.Printf("%p\n", header) + header, data, err = Pop(header) + if err != nil { + err.Print() + break + } + + fmt.Printf("[%d]>>> %v\n", i, data) + } + + for i := 0; i < 128; i++ { + err := Push(header, i) + if err != nil { + err.Print() + break + } + } + + for i := 0; i < 128; i++ { + var data interface{} + var err *icserror.IcsError + //fmt.Printf("%p\n", header) + header, data, err = Pop(header) + if err != nil { + err.Print() + break + } + + fmt.Printf("[%d]>>> %v\n", i, data) + } +} diff --git a/icsevent/icsevent.go b/icsevent/icsevent.go new file mode 100644 index 0000000..a4b24b2 --- /dev/null +++ b/icsevent/icsevent.go @@ -0,0 +1,219 @@ +/* +**************************** +struct Event +**************************** +실제 이벤트 데이터 + +Copy() + 이벤트 데이터 복사 + +**************************** +struct EventH +**************************** +struct Event 핸들링 구조체. singleton이며 전역 변수. +struct Event를 array로 가진다. + +AllocEvent() + array에서 빈 event item을 확보하고 데이터를 넣는다. + +RemoveEvent() + array에서 해당 event를 삭제. + +PostEvent() + 이벤트를 받을 세션에 이벤트를 보낸다. + +GetEvent() + 이벤트 수신. + polling 방식 + +*/ + +package icsevent + +import ( + "sync" + + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" +) + +const ( + MAX_EVENT_NUM = 655360 + MAX_CHANNEL_NUM = 256 +) + +/////////////////////////////////////////////////////////////// +// 단위 이벤트 +type Event struct { + Data *interface{} + ID int + //m *sync.Mutex +} + +func (e *Event) GetData() *interface{} { + return e.Data +} + +/////////////////////////////////////////////////////////////// +// 전역 이벤트 배열 +type EventH struct { + evtArray []*Event + m *sync.Mutex +} + +var eventData []*Event +var onceEvent sync.Once +var onceEventInit sync.Once + +var channelNum int = MAX_CHANNEL_NUM +var eventNum int = MAX_EVENT_NUM +var lastPos int + +func getEventInstance() []*Event { + onceEvent.Do(func() { + eventData = make([]*Event, eventNum) + for iter := 0; iter < eventNum; iter++ { + eventData[iter] = new(Event) + //eventData[iter].m = &sync.Mutex{} + } + lastPos = 0 + }) + + return eventData +} + +//make global Event Array +func NewEventH() *EventH { + //s := icssvc.NewService() + //channelNum = s.GetIcsConfig().GetChannelNum() + //TODO: add recover + + h := &EventH{} + h.evtArray = getEventInstance() + h.m = &sync.Mutex{} + + return h +} + +//initialize Event Array +func (h *EventH) Init() { + onceEventInit.Do(func() { + for iter := 0; iter < eventNum; iter++ { + h.evtArray[iter].Data = nil + h.evtArray[iter].ID = iter + } + }) +} + +//put data to event array +func (h *EventH) AllocEvent(data interface{}) (*Event, *icserror.IcsError) { + count := 0 + for iter := lastPos; count < eventNum; iter++ { + if iter == eventNum { + iter = 0 + } + + //h.evtArray[iter].m.Lock() + h.m.Lock() + if h.evtArray[iter].Data == nil { + h.evtArray[iter].Data = &data + lastPos = iter + 1 + //h.evtArray[iter].m.Unlock() + h.m.Unlock() + return h.evtArray[iter], nil + } + //h.evtArray[iter].m.Unlock() + h.m.Unlock() + count++ + } + + return nil, icserror.ICSERREVTAlloc +} + +//remove data from Event Array +func (h *EventH) RemoveEvent(event *Event) *icserror.IcsError { + if event == nil { + return icserror.ICSERRInvalidParam + } + + if h.evtArray[event.ID].Data == nil { + return icserror.ICSERREVTRemove + } + + //h.evtArray[event.ID].m.Lock() + h.m.Lock() + h.evtArray[event.ID].Data = nil + //h.evtArray[event.ID].m.Unlock() + h.m.Unlock() + + return nil +} + +func (h *EventH) removeEvent(id int) *icserror.IcsError { + if h.evtArray[id].Data == nil { + return icserror.ICSERREVTRemove + } + + //h.evtArray[id].m.Lock() + h.m.Lock() + h.evtArray[id].Data = nil + //h.evtArray[id].m.Unlock() + h.m.Unlock() + + return nil +} + +func (h *EventH) Copy(src *Event, dst *Event) *icserror.IcsError { + if dst == nil { + return icserror.ICSERRInvalidParam + } + + //e.m.Lock() + h.m.Lock() + dst.Data = src.Data + dst.ID = src.ID + h.m.Unlock() + //e.m.Unlock() + + return nil +} + +func (h *EventH) PostEvent(targetID int, event *Event) *icserror.IcsError { + if targetID < 0 || event == nil { + return icserror.ICSERRInvalidParam + } + + target := GetEvtSystemInstance() + q := target[targetID] + esErr := q.PutJob(event) + if esErr != nil { + + return esErr + } + + return nil +} + +func (h *EventH) GetEvent(targetID int) (*Event, *icserror.IcsError) { + if targetID < 0 { + return nil, icserror.ICSERRInvalidParam + } + + target := GetEvtSystemInstance() + q := target[targetID] + pos, esErr := q.GetJob() + if esErr != nil || pos < 0 { + return nil, esErr + } + + e := &Event{} + //h.evtArray[pos].Copy(e) + h.Copy(h.evtArray[pos], e) + h.RemoveEvent(h.evtArray[pos]) + + return e, nil +} + +//FOR ONLY DEBUG. DO NOT USE THIS FUNCTION-getEvt()! +func (h *EventH) getEvt(eventID int) *Event { + return h.evtArray[eventID] +} diff --git a/icsevent/icseventsystem.go b/icsevent/icseventsystem.go new file mode 100644 index 0000000..6e79a7c --- /dev/null +++ b/icsevent/icseventsystem.go @@ -0,0 +1,118 @@ +/* +**************************** +struct EventSystem +**************************** +session의 Job queue +각 세션마다 자기 자신이 처리해야 할 Event struct의 Event ID를 저장하는 JobQ를 가진다. +*/ + +package icsevent + +import ( + "sync" + + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" +) + +/////////////////////////////////////////////////////////////// +//전역 세션용 이벤트 시스템 구조체. +type EventSystem struct { + id int //session id + JobQ *RRData //event id q for session + m *sync.Mutex +} + +var bigEvtSystem []*EventSystem +var onceEvtSystem sync.Once + +//make singleton EventSystem struct +func GetEvtSystemInstance() []*EventSystem { + onceEvtSystem.Do(func() { + bigEvtSystem = make([]*EventSystem, channelNum) + + for iter := 0; iter < channelNum; iter++ { + bigEvtSystem[iter] = new(EventSystem) + bigEvtSystem[iter].Init(iter) + } + }) + + return bigEvtSystem +} + +func SetChannelNum(chNum int) { + channelNum = chNum +} + +func (es *EventSystem) Init(id int) { + es.id = id + es.JobQ = NewRRData() + es.m = &sync.Mutex{} +} + +func GetMyEventSystem(id int) *EventSystem { + es := GetEvtSystemInstance() + return es[id] +} + +func (es *EventSystem) GetMyID() int { + return es.id +} + +func (es *EventSystem) PutJob(event *Event) (err *icserror.IcsError) { + if event == nil { + return icserror.ICSERRInvalidParam + } + if es.JobQ == nil { + return icserror.ICSERREVTNotInit + } + + es.m.Lock() + rrerr := Push(es.JobQ, event.ID) + if rrerr != nil { + es.m.Unlock() + return rrerr + } + es.m.Unlock() + + return nil +} + +func (es *EventSystem) GetJob() (pos int, err *icserror.IcsError) { + if es.JobQ == nil { + return -1, icserror.ICSERREVTNotInit + } + + es.m.Lock() + var data interface{} + var h *RRData + h, data, err = Pop(es.JobQ) + //es.JobQ, data, err = icsutil.Pop(es.JobQ) + if err != nil || data == nil { + //err.Print() + es.m.Unlock() + return -1, err + } + + switch v := data.(type) { + case int: + es.JobQ = h + pos = v + + default: + pos = -1 + es.m.Unlock() + return pos, nil + } + es.m.Unlock() + + return pos, nil +} + +func (es *EventSystem) ClearJob() (err *icserror.IcsError) { + h := NewEventH() + for pos, err := es.GetJob(); err != nil; { + h.removeEvent(pos) + } + + return nil +} diff --git a/icslog/icslog.go b/icslog/icslog.go new file mode 100644 index 0000000..36f2fa4 --- /dev/null +++ b/icslog/icslog.go @@ -0,0 +1,298 @@ +package icslog + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "runtime/debug" + "strconv" + "strings" + "sync" + "time" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icsutil" +) + +type IcsLog struct { + logger *log.Logger + + Output int + Level int + Path string + LogFileName string + LogFile *os.File + DiskLimit int + DelDay int + DelHour int + isRotate bool + logSize int + rotateNum int + + buf bytes.Buffer + CurrentDate time.Time + conf *icsconf.LogConfig + //conf *icsconf.IcsConfig + IsDiskFull bool + + M *sync.Mutex +} + +//default max log size 30 megabytes +const DEFAULT_LOG_MAX_SIZE = 30 + +//default log rotate num +const DEFAULT_LOG_ROTATE_NUM = 10 + +//max log rotate num +const MAX_LOG_ROTATE_NUM = 99 + +const ( + LOG_LEVEL_DEBUG2 = iota + LOG_LEVEL_DEBUG1 + LOG_LEVEL_DEBUG + LOG_LEVEL_STATIS + LOG_LEVEL_INFO + LOG_LEVEL_WARN + LOG_LEVEL_ERROR + LOG_LEVEL_FATAL + LOG_LEVEL_MAX +) + +//log output +const ( + LOG_OUTPUT_FILE = 1 << (32 - 1 - iota) + LOG_OUTPUT_STDOUT +) + +var IcsLogLevelStr [LOG_LEVEL_MAX]string + +var gIcsLog *IcsLog +var onceLog sync.Once + +func init() { + IcsLogLevelStr[LOG_LEVEL_DEBUG2] = "DEBUG2" + IcsLogLevelStr[LOG_LEVEL_DEBUG1] = "DEBUG1" + IcsLogLevelStr[LOG_LEVEL_DEBUG] = "DEBUG" + IcsLogLevelStr[LOG_LEVEL_STATIS] = "STATISTICS" + IcsLogLevelStr[LOG_LEVEL_INFO] = "INFO" + IcsLogLevelStr[LOG_LEVEL_WARN] = "WARN" + IcsLogLevelStr[LOG_LEVEL_ERROR] = "ERROR" + IcsLogLevelStr[LOG_LEVEL_FATAL] = "FATAL" +} + +//if fail, return icserror +func NewIcsLog(conf *icsconf.LogConfig, level int, output int, path string, disklimit int) (*IcsLog, *icserror.IcsError) { + //func NewIcsLog(conf *icsconf.IcsConfig, level int, output int, path string, disklimit int) (*IcsLog, *icserror.IcsError) { + //func NewIcsLog(conf *icsconf.IcsConfig, level interface{}, output interface{}, path string, disklimit int) (*IcsLog, *icserror.IcsError) { + var reterr *icserror.IcsError = nil + + //singleton + onceLog.Do(func() { + gIcsLog = &IcsLog{ + conf: conf, + Level: level, + Output: output, + Path: path, + DiskLimit: disklimit, + IsDiskFull: false, + logSize: DEFAULT_LOG_MAX_SIZE, + rotateNum: DEFAULT_LOG_ROTATE_NUM, + } + + gIcsLog.M = &sync.Mutex{} + gIcsLog.isRotate = strings.Compare("YES", strings.ToUpper(gIcsLog.conf.RotateConfig.YesNo)) == 0 + //gIcsLog.isRotate = strings.Compare("YES", strings.ToUpper(gIcsLog.conf.LogConfig.RotateConfig.YesNo)) == 0 + var serr error + gIcsLog.logSize, serr = strconv.Atoi(gIcsLog.conf.RotateConfig.Size) + //gIcsLog.logSize, serr = strconv.Atoi(gIcsLog.conf.LogConfig.RotateConfig.Size) + if serr != nil { + gIcsLog.logSize = DEFAULT_LOG_MAX_SIZE + } + gIcsLog.rotateNum, serr = strconv.Atoi(gIcsLog.conf.RotateConfig.Num) + //gIcsLog.rotateNum, serr = strconv.Atoi(gIcsLog.conf.LogConfig.RotateConfig.Num) + if serr != nil { + gIcsLog.rotateNum = DEFAULT_LOG_ROTATE_NUM + } + if gIcsLog.rotateNum > MAX_LOG_ROTATE_NUM { + gIcsLog.rotateNum = MAX_LOG_ROTATE_NUM + } + + gIcsLog.logger = log.New(&gIcsLog.buf, "", log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile) + + gIcsLog.CurrentDate = time.Now() + gIcsLog.DelDay = conf.DelConfig.DelDay + gIcsLog.DelHour = conf.DelConfig.DelHour + + //make log file - icsvg.log-yyyymmdd + yyyy, mm, dd := gIcsLog.CurrentDate.Date() + gIcsLog.LogFileName = fmt.Sprintf("%s/icsvs.log-%d%02d%02d", gIcsLog.Path, yyyy, mm, dd) + + stat, err := os.Stat(gIcsLog.LogFileName) + if err == nil { + if gIcsLog.checkLogRotate() && stat.Size()/ONEMB >= int64(gIcsLog.logSize) { + rotateNum := gIcsLog.getTodayLogFileNum() + //fmt.Println("rotate num:", rotateNum) + if rotateNum > 0 && rotateNum < gIcsLog.rotateNum { + gIcsLog.shiftLogFiles(rotateNum) + + var oerr error + oerr = os.MkdirAll(filepath.Dir(gIcsLog.LogFileName), 0777) + if oerr != nil { + icserror.ICSERRMakeDir.SetError(oerr) + icserror.ICSERRMakeDir.PrintWithCaller(0) + return + } + + gIcsLog.LogFile, oerr = os.OpenFile(gIcsLog.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if oerr != nil { + //fmt.Println(gIcsLog.LogFileName) + icserror.ICSERRFileOpen.SetError(oerr) + reterr = icserror.ICSERRFileOpen + reterr.PrintWithCaller(0) + return + } + } + } else if stat.Size()/ONEMB < int64(gIcsLog.logSize) { + var oerr error + oerr = os.MkdirAll(filepath.Dir(gIcsLog.LogFileName), 0777) + if oerr != nil { + icserror.ICSERRMakeDir.SetError(oerr) + icserror.ICSERRMakeDir.PrintWithCaller(0) + return + } + + gIcsLog.LogFile, oerr = os.OpenFile(gIcsLog.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if oerr != nil { + //fmt.Println(gIcsLog.LogFileName) + icserror.ICSERRFileOpen.SetError(oerr) + reterr = icserror.ICSERRFileOpen + reterr.PrintWithCaller(0) + return + } + } + } else { + var oerr error + oerr = os.MkdirAll(filepath.Dir(gIcsLog.LogFileName), 0777) + if oerr != nil { + icserror.ICSERRMakeDir.SetError(oerr) + icserror.ICSERRMakeDir.PrintWithCaller(0) + return + } + + gIcsLog.LogFile, oerr = os.OpenFile(gIcsLog.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if oerr != nil { + //fmt.Println(gIcsLog.LogFileName) + icserror.ICSERRFileOpen.SetError(oerr) + reterr = icserror.ICSERRFileOpen + reterr.PrintWithCaller(0) + return + } + } + + }) + + return gIcsLog, reterr +} + +func GetIcsLog() *IcsLog { + return gIcsLog +} + +func GetLogLevelID(str string) int { + switch str { + case "DEBUG2": + return LOG_LEVEL_DEBUG2 + case "DEBUG1": + return LOG_LEVEL_DEBUG1 + case "DEBUG": + return LOG_LEVEL_DEBUG + case "STATISTICS": + return LOG_LEVEL_STATIS + case "INFO": + return LOG_LEVEL_INFO + case "WARN": + return LOG_LEVEL_WARN + case "ERROR": + return LOG_LEVEL_ERROR + case "FATAL": + return LOG_LEVEL_FATAL + default: + return -1 + } +} + +func GetLogOutputID(str string) int { + switch str { + case "FILE": + return LOG_OUTPUT_FILE + default: + return LOG_OUTPUT_STDOUT + } +} + +func (s *IcsLog) DelLog() { + //var derr *icserror.IcsError = nil + delLogCount := 0 + + defer func() { + if err := recover(); err != nil { + switch v := err.(type) { + case error: + icserror.ICSERRFileOpen.SetError(v) + s.Printf(LOG_LEVEL_WARN, -1, "PANIC! %s\n%s", icserror.ICSERRFileOpen.GetError().Error(), string(debug.Stack())) + default: + s.Print(LOG_LEVEL_WARN, -1, icserror.ICSERRFileOpen.GetError().Error()) + } + } + //derr = icserror.ICSERRFileOpen + }() + + // 1. Get Log Del Time + yyyy, mm, dd := s.CurrentDate.Date() + curTime, _ := time.Parse("2006-01-02", fmt.Sprintf("%d-%02d-%02d", yyyy, mm, dd)) + delTime := curTime.AddDate(0, 0, -s.DelDay) + + files, rderr := ioutil.ReadDir(s.Path) + if rderr != nil { + s.Printf(LOG_LEVEL_ERROR, -1, " Read Log Dir error - %s \n", rderr) + fmt.Printf("Read Log Dir error - %s", rderr) + } else { + var logYYYY, logMM, logDD string + for _, file := range files { + /* + TODO + 1. 로그 파일을 시간으로 변환 + 2. 현재 시간 - 삭제기간 + 3. 둘 시간 차이가 0 이상 나면 삭제대상 + */ + logTime := strings.SplitN(file.Name(), "-", -1)[1] + logYYYY, logMM, logDD = logTime[:4], logTime[4:6], logTime[6:8] + chgLogTime, perr := time.Parse("2006-01-02", fmt.Sprintf("%s-%s-%s", logYYYY, logMM, logDD)) + if perr != nil { + s.Printf(LOG_LEVEL_ERROR, -1, " Log Time Parse error - %s \n", perr) + fmt.Printf("Log Time Parse error - %s", perr) + } else { + diff := delTime.Sub(chgLogTime) + + // diff > 0 => delete log + if diff > 0 { + delResult := icsutil.DeleteFile(s.Path, file.Name()) + if delResult != "" { + s.Printf(LOG_LEVEL_ERROR, -1, " Delete File error - %s \n", delResult) + } else { + s.Printf(LOG_LEVEL_INFO, -1, " Delete %s!!!!\n", file.Name()) + fmt.Printf("Delete %s!!!!\n", file.Name()) + delLogCount += 1 + } + } + } + } + } + s.Printf(LOG_LEVEL_INFO, -1, " Delete File Count - %d \n", delLogCount) + fmt.Printf("Log Delete Count : %d", delLogCount) +} diff --git a/icslog/loglevel.go b/icslog/loglevel.go new file mode 100644 index 0000000..ae2bd13 --- /dev/null +++ b/icslog/loglevel.go @@ -0,0 +1,22 @@ +package icslog + +import "sync" + +type LogLevel struct { + currentLevel interface{} + m sync.Mutex +} + +func (l *LogLevel) SetLogLevel(level interface{}) { + l.m.Lock() + defer l.m.Unlock() + + l.currentLevel = level +} + +func (l *LogLevel) GetLogLevel() (level interface{}) { + l.m.Lock() + defer l.m.Unlock() + + return l.currentLevel +} diff --git a/icslog/logoutput.go b/icslog/logoutput.go new file mode 100644 index 0000000..98f2283 --- /dev/null +++ b/icslog/logoutput.go @@ -0,0 +1,199 @@ +package icslog + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strconv" + "strings" + + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icsutil" +) + +const ( + ONEMB = 1048576 +) + +func (l *IcsLog) Printf(level int, sessionID int, format string, a ...interface{}) { + msg := fmt.Sprintf(format, a...) + + if level >= l.Level { + //check disk full + aSpace := icsutil.GetDiskAvailableSpace(filepath.Dir(l.LogFileName)) + if aSpace < uint64(l.conf.Disklimit*ONEMB) { + //if aSpace < uint64(l.conf.LogConfig.Disklimit*ONEMB) { + if !l.IsDiskFull { + msg = fmt.Sprintf("Disk Full! Available Disk Space: %dMB", aSpace/ONEMB) + l.logger.Output(2, msg) + if l.LogFile != nil { + l.LogFile.WriteString(l.buf.String()) + } + l.buf.Reset() + l.IsDiskFull = true + } + return + } + + l.M.Lock() + + if l.checkLogRotate() { + //check log size + stat, err := os.Stat(l.LogFileName) + if err != nil { + msg = fmt.Sprintf("Could not get log file(%s) size", l.LogFileName) + l.logger.Output(2, msg) + if l.LogFile != nil { + l.LogFile.WriteString(l.buf.String()) + } + l.buf.Reset() + + l.M.Unlock() + + return + } + + if stat.Size()/ONEMB >= int64(l.logSize) { + //shift log files + rotateNum := gIcsLog.getTodayLogFileNum() + if rotateNum > 0 && rotateNum < gIcsLog.rotateNum { + gIcsLog.shiftLogFiles(rotateNum) + + l.LogFile.Sync() + l.LogFile.Close() + + //open new log file + var oerr error + //fmt.Println("LOG rotate new log file", l.LogFileName) + l.LogFile, oerr = os.OpenFile(l.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if oerr != nil { + icserror.ICSERRFileOpen.SetError(oerr) + icserror.ICSERRFileOpen.PrintWithCaller(1) + + l.M.Unlock() + return + } + } else { + l.M.Unlock() + return + } + } + } + + //write log + if level < LOG_LEVEL_DEBUG2 || level > LOG_LEVEL_FATAL { + level = LOG_LEVEL_INFO + } + var logmsg string + if sessionID >= 0 { + logmsg = fmt.Sprintf("[%s][%03d]> %s", IcsLogLevelStr[level], sessionID, msg) + } else { + logmsg = fmt.Sprintf("[%s][-1]> %s", IcsLogLevelStr[level], msg) + } + + l.logger.Output(2, logmsg) + if l.LogFile != nil { + l.LogFile.WriteString(l.buf.String()) + } + l.buf.Reset() + + l.M.Unlock() + } + +} + +func (l *IcsLog) Print(level int, sessionID int, msg string) { + if level >= l.Level { + //check disk full + aSpace := icsutil.GetDiskAvailableSpace(filepath.Dir(l.LogFileName)) + if aSpace < uint64(l.conf.Disklimit*ONEMB) { + //if aSpace < uint64(l.conf.LogConfig.Disklimit*ONEMB) { + if !l.IsDiskFull { + msg = fmt.Sprintf("Disk Full! Available Disk Space: %dMB", aSpace/ONEMB) + l.logger.Output(2, msg) + if l.LogFile != nil { + l.LogFile.WriteString(l.buf.String()) + } + l.buf.Reset() + l.IsDiskFull = true + } + return + } + + l.M.Lock() + + if l.checkLogRotate() { + //check log size + stat, err := os.Stat(l.LogFileName) + if err != nil { + msg = fmt.Sprintf("Could not get log file(%s) size", l.LogFileName) + l.logger.Output(2, msg) + if l.LogFile != nil { + l.LogFile.WriteString(l.buf.String()) + } + l.buf.Reset() + + l.M.Unlock() + + return + } + + if stat.Size()/ONEMB >= int64(l.logSize) { + //shift log files + rotateNum := gIcsLog.getTodayLogFileNum() + //fmt.Println("rotate num:", rotateNum, "log size:", stat.Size()/ONEMB, l.logSize) + if rotateNum > 0 && rotateNum < gIcsLog.rotateNum { + gIcsLog.shiftLogFiles(rotateNum) + + l.LogFile.Sync() + l.LogFile.Close() + + //open new log file + var oerr error + l.LogFile, oerr = os.OpenFile(l.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if oerr != nil { + icserror.ICSERRFileOpen.SetError(oerr) + icserror.ICSERRFileOpen.PrintWithCaller(1) + + l.M.Unlock() + return + } + } else { + l.M.Unlock() + return + } + + } + } + + //write log + if level < LOG_LEVEL_DEBUG2 || level > LOG_LEVEL_FATAL { + level = LOG_LEVEL_INFO + } + var logmsg string + if sessionID >= 0 { + logmsg = fmt.Sprintf("[%s][%03d]> %s", IcsLogLevelStr[level], sessionID, msg) + } else { + logmsg = fmt.Sprintf("[%s][-1]> %s", IcsLogLevelStr[level], msg) + } + l.logger.Output(2, logmsg) + if l.LogFile != nil { + l.LogFile.WriteString(l.buf.String()) + } + l.buf.Reset() + + l.M.Unlock() + } +} + +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 +} diff --git a/icslog/logrotate.go b/icslog/logrotate.go new file mode 100644 index 0000000..c60062d --- /dev/null +++ b/icslog/logrotate.go @@ -0,0 +1,71 @@ +package icslog + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +//returns created log file numnber in today +func (l *IcsLog) getTodayLogFileNum() int { + dir := filepath.Dir(l.LogFileName) + files, rerr := os.ReadDir(dir) + if rerr != nil { + return 0 + } + iter := 0 + for _, file := range files { + if !file.IsDir() { + if strings.Contains(file.Name(), filepath.Base(l.LogFileName)) { + iter++ + } + } + } + + if iter > MAX_LOG_ROTATE_NUM { + return 0 + } + + return iter +} + +func (l *IcsLog) shiftLogFiles(filenum int) { + dir := filepath.Dir(l.LogFileName) + files, rerr := os.ReadDir(dir) + if rerr != nil { + return + } + + //l.M.Lock() + remFileNum := filenum + filesLen := len(files) - 1 + for file := files[filesLen]; ; file = files[filesLen] { + if !file.IsDir() { + //fmt.Println(">>333", file.Name(), filepath.Base(l.LogFileName)) + if strings.Contains(file.Name(), filepath.Base(l.LogFileName)) { + //fmt.Println(filesLen, file.Name()) + old := fmt.Sprintf("%s/%s", dir, file.Name()) + //fmt.Println(old) + new := fmt.Sprintf("%s.%02d", l.LogFileName, remFileNum) + //fmt.Println(new) + os.Rename(old, new) + remFileNum-- + if remFileNum < 0 { + //fmt.Println(">666") + break + } + //fmt.Println(">444") + } + } + filesLen-- + if filesLen < 0 { + break + } + } + //l.M.Unlock() +} + +func (l *IcsLog) checkLogRotate() bool { + return l.isRotate +} diff --git a/icsnet/icsnet.go b/icsnet/icsnet.go new file mode 100644 index 0000000..1d31a0d --- /dev/null +++ b/icsnet/icsnet.go @@ -0,0 +1,64 @@ +package icsnet + +import ( + "fmt" + "net" + + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" +) + +var MAX_MTU int = 1500 + +type IcsNeter interface { + Listen() *icserror.IcsError + + Connect(localAddr, remoteAddr *IcsNetAddr) *icserror.IcsError + Close() *icserror.IcsError + + Write(b []byte) (int, *icserror.IcsError) + WriteSIP(b []byte) (int, *icserror.IcsError) + WriteRTP(b []byte) (int, *icserror.IcsError) + + Read(size int) ([]byte, int, *icserror.IcsError) + ReadSIP() ([]byte, *net.UDPAddr, int, *icserror.IcsError) + ReadRTP() ([]byte, *net.UDPAddr, int, *icserror.IcsError) + + LocalAddr() net.Addr + RemoteAddr() net.Addr + SetRemoteAddr(raddr *IcsNetAddr) +} + +type IcsConn struct { + ICSUDPConn *net.UDPConn + ICSTCPConn *net.TCPConn +} + +func GetMyIP() ([]string, *icserror.IcsError) { + var retIP []string + ifaces, err := net.Interfaces() + if err != nil { + icserror.ICSERRNETNotFoundIF.SetError(err) + return nil, icserror.ICSERRNETNotFoundIF + } + + for iter, i := range ifaces { + addrs, err := i.Addrs() + // handle err + if err != nil { + icserror.ICSERRNETGetAddr.SetError(err) + return nil, icserror.ICSERRNETGetAddr + } + for _, addr := range addrs { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + retIP[iter] = fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]) + } + } + + return retIP, nil +} diff --git a/icsnet/icsnetaddr.go b/icsnet/icsnetaddr.go new file mode 100644 index 0000000..edb2971 --- /dev/null +++ b/icsnet/icsnetaddr.go @@ -0,0 +1,122 @@ +package icsnet + +import ( + "fmt" + "net" + "strconv" + "strings" + + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" +) + +type IcsNetAddr struct { + IPv4 []byte + IPv4String string + Port int +} + +func NewNetAddr() IcsNetAddr { + addr := IcsNetAddr{} + addr.IPv4 = make([]byte, 4) + + return addr +} + +//format 123.123.123.123:9999 +func NewNetAddrWithIPAddr(ipaddr string) IcsNetAddr { + addr := IcsNetAddr{} + addr.IPv4 = make([]byte, 4) + + spl := strings.Split(ipaddr, ":") + addr.SetIPv4String(spl[0]) + var err error + addr.Port, err = strconv.Atoi(spl[1]) + if err != nil { + addr.Port = 0 + } + + return addr +} + +func NewNetAddrWithIPPort(ip string, port int) IcsNetAddr { + addr := IcsNetAddr{} + addr.IPv4 = make([]byte, 4) + + addr.SetIPv4String(ip) + addr.SetPort(port) + + return addr +} + +func NewIcsNetAddrWithUDPAddr(addr *net.UDPAddr) *IcsNetAddr { + icsaddr := &IcsNetAddr{} + icsaddr.IPv4 = make([]byte, 4) + + icsaddr.SetIPv4String(addr.IP.String()) + icsaddr.SetPort(addr.Port) + + //fmt.Println(">>>>", icsaddr) + return icsaddr +} + +func NewIcsNetAddrWithTCPAddr(addr *net.TCPAddr) *IcsNetAddr { + icsaddr := &IcsNetAddr{} + icsaddr.IPv4 = make([]byte, 4) + + ip, sport, _ := net.SplitHostPort(addr.IP.String()) + port, _ := strconv.Atoi(sport) + icsaddr.SetIPv4String(ip) + icsaddr.SetPort(port) + + return icsaddr +} + +func (a *IcsNetAddr) SetIPv4(ip []byte) { + copy(a.IPv4, ip) + a.IPv4String = fmt.Sprintf("%d.%d.%d.%d", a.IPv4[0], a.IPv4[1], a.IPv4[2], a.IPv4[3]) +} + +func (a *IcsNetAddr) SetIPv4String(ip string) { + a.IPv4String = ip + + no := strings.Split(ip, ".") + for iter, b := range no { + i, err := strconv.Atoi(b) + if err != nil { + i = 0 + } + + a.IPv4[iter] = byte(i) + } +} + +func (a *IcsNetAddr) SetPort(port int) { + a.Port = port +} + +func (a IcsNetAddr) String() string { + strAddr := fmt.Sprintf("%d.%d.%d.%d:%d", a.IPv4[0], a.IPv4[1], a.IPv4[2], a.IPv4[3], a.Port) + return strAddr +} + +func (a IcsNetAddr) ResolveIcsNetAddr(network string) (interface{}, *icserror.IcsError) { + ip := fmt.Sprintf("%d.%d.%d.%d:%d", a.IPv4[0], a.IPv4[1], a.IPv4[2], a.IPv4[3], a.Port) + + if strings.Compare("tcp", network) == 0 { + addr, err := net.ResolveTCPAddr("tcp", ip) + if err != nil { + icserror.ICSERRNETResolveAddrError.SetError(err) + return nil, icserror.ICSERRNETResolveAddrError + } + return interface{}(*addr), nil + } else if strings.Compare("udp", network) == 0 { + addr, err := net.ResolveUDPAddr("udp", ip) + if err != nil { + icserror.ICSERRNETResolveAddrError.SetError(err) + return nil, icserror.ICSERRNETResolveAddrError + } + return interface{}(*addr), nil + } + + return nil, nil +} diff --git a/icsnet/icstcp.go b/icsnet/icstcp.go new file mode 100644 index 0000000..aad400c --- /dev/null +++ b/icsnet/icstcp.go @@ -0,0 +1,283 @@ +package icsnet + +import ( + "net" + "strings" + "time" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icslog" +) + +const ( + NET_BUFFER_LENGTH = 4096 +) + +type IcsTCPNet struct { + laddr *IcsNetAddr + raddr *IcsNetAddr + conn *IcsConn + listener *net.TCPListener +} + +func NewTCP(laddr, raddr *IcsNetAddr) (tcpnet *IcsTCPNet) { + tcpnet = &IcsTCPNet{ + laddr: laddr, + raddr: raddr, + conn: &IcsConn{}, + } + + return tcpnet +} + +func (t *IcsTCPNet) Listen() *icserror.IcsError { + addr, err := t.laddr.ResolveIcsNetAddr("tcp") + if err != nil { + return err + } + + var aerr error + switch v := addr.(type) { + case net.TCPAddr: + t.listener, aerr = net.ListenTCP("tcp", &v) + if aerr != nil { + icserror.ICSERRNETListenError.SetError(aerr) + return icserror.ICSERRNETListenError + } + } + + return nil +} + +func (t *IcsTCPNet) Accept() (conn *net.TCPConn, ierr *icserror.IcsError) { + var err error + if t.listener != nil { + conn, err = t.listener.AcceptTCP() + //t.conn.ICSTCPConn, err = t.listener.AcceptTCP() + if err != nil { + icserror.ICSERRNETAcceptError.SetError(err) + return nil, icserror.ICSERRNETAcceptError + } + } else { + return nil, icserror.ICSERRNETAcceptError + } + + return conn, nil +} + +func (t *IcsTCPNet) Connect(localAddr, remoteAddr *IcsNetAddr) *icserror.IcsError { + if remoteAddr != nil { + t.raddr = remoteAddr + } + raddr, rerr := t.raddr.ResolveIcsNetAddr("tcp") + if rerr != nil { + return rerr + } + + var aerr error + switch v := raddr.(type) { + case net.TCPAddr: + t.conn.ICSTCPConn, aerr = net.DialTCP("tcp", nil, &v) + if aerr != nil { + icserror.ICSERRNETConnectError.SetError(aerr) + return icserror.ICSERRNETConnectError + } + } + + return nil +} + +func (t *IcsTCPNet) Close() *icserror.IcsError { + if t.conn.ICSTCPConn == nil { + return icserror.ICSERRNETNotConnectError + } + + aerr := t.conn.ICSTCPConn.Close() + if aerr != nil { + icserror.ICSERRNETNotConnectError.SetError(aerr) + return icserror.ICSERRNETNotConnectError + } + + return nil +} + +func (t *IcsTCPNet) Write(b []byte) (int, *icserror.IcsError) { + if t.conn.ICSTCPConn == nil { + return 0, icserror.ICSERRNETNotConnectError + } + + wsize, err := t.conn.ICSTCPConn.Write(b) + if err != nil { + icserror.ICSERRNETWriteError.SetError(err) + return -1, icserror.ICSERRNETWriteError + } + + return wsize, nil +} + +func (u *IcsTCPNet) WriteSIP(b []byte) (int, *icserror.IcsError) { + return 0, nil +} + +func (u *IcsTCPNet) WriteRTP(b []byte) (int, *icserror.IcsError) { + return 0, nil +} + +func (t *IcsTCPNet) Read(size int) ([]byte, int, *icserror.IcsError) { + var rlen int = 0 + buf := make([]byte, size) + + for rlen = 0; ; { + len, err := t.conn.ICSTCPConn.Read(buf[rlen:]) + //len, err := t.conn.ICSTCPConn.Read(buf) + if err == nil { + rlen += len + if rlen >= size { + return buf, rlen, nil + } + } else { + icserror.ICSERRNETReadError.SetError(err) + return nil, -1, icserror.ICSERRNETReadError + } + } +} + +func (t *IcsTCPNet) ReadS(length int, lineEnd string) ([]byte, int, *icserror.IcsError) { + var rlen int = 0 + size := NET_BUFFER_LENGTH + if length > 0 { + size = length + } + buf := make([]byte, size) + //fmt.Println("Reads make size:", size, "buf size:", len(buf)) + + for rlen = 0; ; { + rbuf := make([]byte, size) + len, err := t.conn.ICSTCPConn.Read(rbuf) + if err == nil { + rlen += len + copy(buf[:rlen], rbuf) + if rlen >= size { + return buf, rlen, nil + } else if strings.Contains(string(buf), lineEnd) { + return buf, rlen, nil + } + } else { + icserror.ICSERRNETReadError.SetError(err) + return nil, -1, icserror.ICSERRNETReadError + } + } +} + +func (u *IcsTCPNet) ReadSIP() ([]byte, *net.UDPAddr, int, *icserror.IcsError) { + return nil, nil, 0, nil +} + +func (u *IcsTCPNet) ReadRTP() ([]byte, *net.UDPAddr, int, *icserror.IcsError) { + return nil, nil, 0, nil +} + +func (t *IcsTCPNet) LocalAddr() net.Addr { + return t.conn.ICSTCPConn.LocalAddr() +} + +func (t *IcsTCPNet) RemoteAddr() net.Addr { + return t.conn.ICSTCPConn.RemoteAddr() +} + +func (t *IcsTCPNet) SetRemoteAddr(raddr *IcsNetAddr) { + t.raddr = raddr +} + +// func (t *IcsTCPNet) SetLinger(sec int) { +// t.conn.ICSTCPConn.SetLinger(sec) +// } + +func (t *IcsTCPNet) SetLinger() { + conf := icsconf.GetIcsConfig() + t.conn.ICSTCPConn.SetLinger(conf.Linger) +} + +func (t *IcsTCPNet) SetDeadline(sec int64) { + t.conn.ICSTCPConn.SetDeadline(time.Now().Add(time.Second * time.Duration(sec))) +} + +func (t *IcsTCPNet) SetWriteDeadline(sec int64) { + t.conn.ICSTCPConn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(sec))) +} + +func (t *IcsTCPNet) SetReadDeadline(sec int64) { + t.conn.ICSTCPConn.SetReadDeadline(time.Now().Add(time.Second * time.Duration(sec))) +} + +func SendCallSignal(laddr, raddr *IcsNetAddr, buf []byte) (t *IcsTCPNet, sendlen int, err *icserror.IcsError) { + t = NewTCP(laddr, raddr) + //connect to VoiceAgent + err = t.Connect(laddr, raddr) + if err != nil { + return nil, -1, err + } + //defer t.Close() + + // t.SetLinger(1) + t.SetLinger() + t.SetDeadline(180) + + //send call signal + sendlen, err = t.Write(buf) + if err != nil { + return nil, -1, err + } + + return t, sendlen, err +} + +//func ListenAndServeTCP(laddr, raddr *IcsNetAddr, bufend string, f func(*net.TCPConn, string)) (t *IcsTCPNet, err *icserror.IcsError) { +func ListenAndServeTCP(laddr, raddr *IcsNetAddr, bufend string, f func(*IcsTCPNet, string)) (t *IcsTCPNet, err *icserror.IcsError) { + t = NewTCP(laddr, raddr) + err = t.Listen() + if err != nil { + return nil, err + } + //defer t.listener.Close() + + l := icslog.GetIcsLog() + go func() { + //fmt.Printf("Started TCP Listen - %s\n", laddr.String()) + l.Printf(icslog.LOG_LEVEL_INFO, -1, "Started TCP Listen - %s", laddr.String()) + + for { + var conn *net.TCPConn + var accepterr *icserror.IcsError + if conn, accepterr = t.Accept(); accepterr != nil { + //if accepterr := t.Accept(); accepterr != nil { + continue + } + newT := NewTCP(nil, nil) + newT.conn.ICSTCPConn = conn + // newT.SetLinger(1) + newT.SetLinger() + newT.SetDeadline(180) + l.Printf(icslog.LOG_LEVEL_DEBUG, -1, "Connected - [%s][%s]", conn.LocalAddr(), conn.RemoteAddr()) + //go f(conn, bufend) + go f(newT, bufend) + } + }() + + return +} + +func (t *IcsTCPNet) CloseListener() *icserror.IcsError { + if t.listener == nil { + return icserror.ICSERRNETNotConnectError + } + + aerr := t.listener.Close() + if aerr != nil { + icserror.ICSERRNETNotConnectError.SetError(aerr) + return icserror.ICSERRNETNotConnectError + } + + return nil +} diff --git a/icsnet/icsudp.go b/icsnet/icsudp.go new file mode 100644 index 0000000..115bb13 --- /dev/null +++ b/icsnet/icsudp.go @@ -0,0 +1,267 @@ +package icsnet + +import ( + "net" + "strconv" + "time" + + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" +) + +type IcsUDPNet struct { + laddr *IcsNetAddr + raddr *IcsNetAddr + conn *IcsConn +} + +func NewUDP(laddr, raddr *IcsNetAddr) (udpnet *IcsUDPNet) { + udpnet = &IcsUDPNet{ + laddr: laddr, + raddr: raddr, + conn: &IcsConn{}, + } + + return udpnet +} + +func (u *IcsUDPNet) GetRemoteAddr() *IcsNetAddr { + addr := u.conn.ICSUDPConn.RemoteAddr() + if addr == nil { + return nil + } + ip, sport, _ := net.SplitHostPort(addr.String()) + port, _ := strconv.Atoi(sport) + + ret := NewNetAddrWithIPPort(ip, port) + return &ret +} + +func (u *IcsUDPNet) SetRemoteAddr(raddr *IcsNetAddr) { + u.raddr = raddr +} + +func (u *IcsUDPNet) Listen() *icserror.IcsError { + addr, err := u.laddr.ResolveIcsNetAddr("udp") + if err != nil { + return err + } + + var aerr error + switch v := addr.(type) { + case net.UDPAddr: + u.conn.ICSUDPConn, aerr = net.ListenUDP("udp4", &v) + if aerr != nil { + icserror.ICSERRNETListenError.SetError(aerr) + return icserror.ICSERRNETListenError + } + } + + return nil +} + +func (u *IcsUDPNet) Connect(localAddr, remoteAddr *IcsNetAddr) *icserror.IcsError { + //var ra *net.UDPAddr + var la, ra *net.UDPAddr + + if localAddr != nil { + u.laddr = localAddr + } + if remoteAddr != nil { + u.raddr = remoteAddr + } + + if u.laddr != nil { + laddr, err := u.laddr.ResolveIcsNetAddr("udp") + if err != nil { + return err + } + switch v := laddr.(type) { + case net.UDPAddr: + la = &v + } + } else { + la = nil + } + + if u.raddr != nil { + raddr, err := u.raddr.ResolveIcsNetAddr("udp") + if err != nil { + return err + } + switch v := raddr.(type) { + case net.UDPAddr: + ra = &v + } + } else { + return icserror.ICSERRInvalidParam + } + + var derr error + u.conn.ICSUDPConn, derr = net.DialUDP("udp", la, ra) + if derr != nil { + icserror.ICSERRNETConnectError.SetError(derr) + return icserror.ICSERRNETConnectError + } + + return nil +} + +func (u *IcsUDPNet) Close() *icserror.IcsError { + //fmt.Println("UDP close!!") + + if u.conn.ICSUDPConn == nil { + return icserror.ICSERRNETNotConnectError + } + + err := u.conn.ICSUDPConn.Close() + if err != nil { + icserror.ICSERRNETCloseError.SetError(err) + return icserror.ICSERRNETCloseError + } + + return nil +} + +func (u *IcsUDPNet) Write(b []byte) (int, *icserror.IcsError) { + if u.conn.ICSUDPConn == nil { + return 0, icserror.ICSERRNETNotConnectError + } + /* + raddr := &net.UDPAddr{ + IP: u.raddr.IPv4, + Port: u.raddr.Port, + } + //fmt.Println("Write addr ", raddr) + wsize, err := u.conn.ICSUDPConn.WriteTo(b, raddr) + */ + //wsize, err := u.conn.ICSUDPConn.WriteToUDP(b, raddr) + wsize, err := u.conn.ICSUDPConn.Write(b) + if err != nil { + icserror.ICSERRNETWriteError.SetError(err) + //fmt.Println("UDP WRITE ERROR -", err) + return -1, icserror.ICSERRNETWriteError + } + return wsize, nil +} + +func (u *IcsUDPNet) WriteSIP(b []byte) (int, *icserror.IcsError) { + if u.conn.ICSUDPConn == nil { + return 0, icserror.ICSERRNETNotConnectError + } + raddr := &net.UDPAddr{ + IP: u.raddr.IPv4, + Port: u.raddr.Port, + } + //fmt.Println("Write addr ", raddr) + //wsize, err := u.conn.ICSUDPConn.WriteTo(b, raddr) + wsize, err := u.conn.ICSUDPConn.WriteToUDP(b, raddr) + //wsize, err := u.conn.ICSUDPConn.Write(b) + if err != nil { + icserror.ICSERRNETWriteError.SetError(err) + //fmt.Println("UDP WRITE ERROR -", err) + return -1, icserror.ICSERRNETWriteError + } + return wsize, nil +} + +func (u *IcsUDPNet) WriteRTP(b []byte) (int, *icserror.IcsError) { + if u.conn.ICSUDPConn == nil { + return 0, icserror.ICSERRNETNotConnectError + } + raddr := &net.UDPAddr{ + IP: u.raddr.IPv4, + Port: u.raddr.Port, + } + //fmt.Println("Write addr ", raddr) + //wsize, err := u.conn.ICSUDPConn.WriteTo(b, raddr) + wsize, err := u.conn.ICSUDPConn.WriteToUDP(b, raddr) + //wsize, err := u.conn.ICSUDPConn.Write(b) + if err != nil { + icserror.ICSERRNETWriteError.SetError(err) + //fmt.Println("UDP WRITE ERROR -", err) + return -1, icserror.ICSERRNETWriteError + } + return wsize, nil +} + +func (u *IcsUDPNet) Read(size int) ([]byte, int, *icserror.IcsError) { + if u.conn.ICSUDPConn == nil { + return nil, -1, icserror.ICSERRNETNotConnectError + } + + buf := make([]byte, size) + + for rlen := 0; ; { + len, err := u.conn.ICSUDPConn.Read(buf) + if err == nil { + //fmt.Println(len, string(buf)) + rlen += len + if rlen >= size { + //fmt.Println(">>>", rlen, string(buf)) + return buf, rlen, nil + } + } else { + icserror.ICSERRNETReadError.SetError(err) + return nil, -1, icserror.ICSERRNETReadError + } + } +} + +func (u *IcsUDPNet) ReadSIP() ([]byte, *net.UDPAddr, int, *icserror.IcsError) { + if u.conn.ICSUDPConn == nil { + return nil, nil, -1, icserror.ICSERRNETNotConnectError + } + + buf := make([]byte, 10240) + + len, addr, err := u.conn.ICSUDPConn.ReadFromUDP(buf[:]) + //len, err := u.conn.ICSUDPConn.Read(buf[:]) + if err == nil { + //fmt.Println("remote addr", u.conn.ICSUDPConn.RemoteAddr(), u.conn.ICSUDPConn.LocalAddr()) + return buf, addr, len, nil + } else { + icserror.ICSERRNETReadError.SetError(err) + return nil, nil, -1, icserror.ICSERRNETReadError + } +} + +func (u *IcsUDPNet) ReadRTP() ([]byte, *net.UDPAddr, int, *icserror.IcsError) { + if u.conn.ICSUDPConn == nil { + return nil, nil, -1, icserror.ICSERRNETNotConnectError + } + + buf := make([]byte, 10240) + + len, addr, err := u.conn.ICSUDPConn.ReadFromUDP(buf[:]) + if err == nil { + //fmt.Println("remote addr", u.conn.ICSUDPConn.RemoteAddr(), u.conn.ICSUDPConn.LocalAddr()) + return buf, addr, len, nil + } else { + icserror.ICSERRNETReadError.SetError(err) + return nil, nil, -1, icserror.ICSERRNETReadError + } +} + +func (u *IcsUDPNet) LocalAddr() net.Addr { + return u.conn.ICSUDPConn.LocalAddr() +} + +func (u *IcsUDPNet) RemoteAddr() net.Addr { + raddr := &net.UDPAddr{ + IP: u.raddr.IPv4, + Port: u.raddr.Port, + } + return raddr +} + +func (u *IcsUDPNet) SetDeadLine(sec int64) { + u.conn.ICSUDPConn.SetDeadline(time.Now().Add(time.Second * time.Duration(sec))) +} + +func (u *IcsUDPNet) SetWriteDeadLine(sec int64) { + u.conn.ICSUDPConn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(sec))) +} + +func (u *IcsUDPNet) SetReadDeadLine(sec int64) { + u.conn.ICSUDPConn.SetReadDeadline(time.Now().Add(time.Second * time.Duration(sec))) +} diff --git a/icsstat/icsstat.go b/icsstat/icsstat.go new file mode 100644 index 0000000..9a54ff8 --- /dev/null +++ b/icsstat/icsstat.go @@ -0,0 +1,256 @@ +package icsstat + +import ( + "fmt" + "io" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icslog" + "gitlab.com/ics_cinnamon/voiceStatistics/icsnet" +) + +type StatInfos struct { + //necessary value + SeqId string // 25 + LogTime string // 14 + LogType string // 3 + Sid string // 50 + ResultCode string // 8 + ReqTime string // 17 + RspTime string // 17 + ClientIp string // 40 + DevInfo string // 5 + OsInfo string // 50 + NwInfo string // 5 + SvcName string // 32 + DevModel string // 50 + CarrierType string // 1 + HostName string // 32 + ScnName string // 32 + + //not necessary + CallId string // 60 + TrId string // 100 + ConcCall string // 5 + SvcType string // 20 + SvcReqTime string // 17 + SvcRspTime string // 17 + ResultMsg string // 256 + SttText string // 8192 + TtsText string // 1024 +} + +const ( + //necessary value + + STAT_INFO = 0 + SEQ_ID = STAT_INFO + 25 + LOG_TIME = SEQ_ID + 14 + LOG_TYPE = LOG_TIME + 3 + SID = LOG_TYPE + 50 + RESULT_CODE = SID + 8 + REQ_TIME = RESULT_CODE + 17 + RES_TIME = REQ_TIME + 17 + CLIENT_IP = RES_TIME + 40 + DEV_INFO = CLIENT_IP + 5 + OS_INFO = DEV_INFO + 50 + NW_INFO = OS_INFO + 5 + SVC_NAME = NW_INFO + 32 + DEV_MODEL = SVC_NAME + 50 + CARRIER_TYPE = DEV_MODEL + 1 + HOST_NAME = CARRIER_TYPE + 32 + SCN_NAME = HOST_NAME + 32 + + //not necessary + CALL_ID = SCN_NAME + 60 + TR_ID = CALL_ID + 100 + CONC_CALL = TR_ID + 5 + SVC_TYPE = CONC_CALL + 20 + SVC_REQ_TIME = SVC_TYPE + 17 + SVC_RSP_TIME = SVC_REQ_TIME + 17 + RESULT_MSG = SVC_RSP_TIME + 17 + STT_TEXT = RESULT_MSG + 256 + TTS_TEXT = STT_TEXT + 8192 //slice 86..? +) + +func ListenStatMNG() (icserr *icserror.IcsError) { + l := icslog.GetIcsLog() + conf := icsconf.GetIcsConfig() + + //start bot-command listen + statPort := conf.Target.TargetPort + statTransport := conf.Target.Transport + statLocalAddrStr := fmt.Sprintf("0.0.0.0:%d", statPort) + statLocalAddr := icsnet.NewNetAddrWithIPAddr(statLocalAddrStr) + + var cmdErr *icserror.IcsError + statTCP, cmdErr := icsnet.ListenAndServeTCP(&statLocalAddr, 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 Stat TCP Command %s port[%d]", statTransport, statPort) + fmt.Println(statTCP) + + return nil +} + +func BotCommand(t *icsnet.IcsTCPNet, bufend string) { + l := icslog.GetIcsLog() + statInfos := new(StatInfos) + + defer t.Close() + l.Printf(icslog.LOG_LEVEL_INFO, -1, "Connected from - %s", t.RemoteAddr()) + + for { + statReads, rlen, rerr := t.ReadS(10018, bufend) // 여기서 전체 몇 byte씩 읽어서 로그를 찍을건지 알아야함 + if rerr != nil { + if rerr.GetError() != io.EOF { + l.Printf(icslog.LOG_LEVEL_ERROR, -1, "[Stat Command] ReadS Error! - %s[%d:%d]", + rerr.GetError(), rlen, len(statReads)) + } + break + } else { + fmt.Printf("Recved Stat Command(%s) %d \n", statReads, rlen) + statInfos.ChangeByteToString(statReads) + + insLog := "" + insLog += fmt.Sprintf("%s\n", statInfos.CallId) + insLog += fmt.Sprintf("%s\n", statInfos.SeqId) + insLog += fmt.Sprintf("%s\n", statInfos.LogTime) + insLog += fmt.Sprintf("%s\n", statInfos.LogType) + insLog += fmt.Sprintf("%s\n", statInfos.Sid) + insLog += fmt.Sprintf("%s\n", statInfos.ResultCode) + insLog += fmt.Sprintf("%s\n", statInfos.ReqTime) + insLog += fmt.Sprintf("%s\n", statInfos.RspTime) + insLog += fmt.Sprintf("%s\n", statInfos.ClientIp) + insLog += fmt.Sprintf("%s\n", statInfos.DevInfo) + insLog += fmt.Sprintf("%s\n", statInfos.OsInfo) + insLog += fmt.Sprintf("%s\n", statInfos.NwInfo) + insLog += fmt.Sprintf("%s\n", statInfos.SvcName) + insLog += fmt.Sprintf("%s\n", statInfos.DevModel) + insLog += fmt.Sprintf("%s\n", statInfos.CarrierType) + insLog += fmt.Sprintf("%s\n", statInfos.HostName) + insLog += fmt.Sprintf("%s\n", statInfos.ScnName) + insLog += fmt.Sprintf("%s\n", statInfos.CallId) + insLog += fmt.Sprintf("%s\n", statInfos.TrId) + insLog += fmt.Sprintf("%s\n", statInfos.ConcCall) + insLog += fmt.Sprintf("%s\n", statInfos.SvcType) + insLog += fmt.Sprintf("%s\n", statInfos.SvcReqTime) + insLog += fmt.Sprintf("%s\n", statInfos.SvcRspTime) + insLog += fmt.Sprintf("%s\n", statInfos.ResultMsg) + insLog += fmt.Sprintf("%s\n", statInfos.SttText) + insLog += fmt.Sprintf("%s\n", statInfos.TtsText) + + l.Printf(icslog.LOG_LEVEL_INFO, -1, "%s", insLog) + fmt.Printf("stats- %s \n", statInfos.SeqId) + fmt.Printf("stats- %s \n", statInfos.LogTime) + fmt.Printf("stats- %s \n", statInfos.LogType) + fmt.Printf("stats- %s \n", statInfos.Sid) + fmt.Printf("stats- %s \n", statInfos.ResultCode) + fmt.Printf("stats- %s \n", statInfos.ReqTime) + fmt.Printf("stats- %s \n", statInfos.RspTime) + fmt.Printf("stats- %s \n", statInfos.ClientIp) + fmt.Printf("stats- %s \n", statInfos.DevInfo) + fmt.Printf("stats- %s \n", statInfos.OsInfo) + fmt.Printf("stats- %s \n", statInfos.NwInfo) + fmt.Printf("stats- %s \n", statInfos.SvcName) + fmt.Printf("stats- %s \n", statInfos.DevModel) + fmt.Printf("stats- %s \n", statInfos.CarrierType) + fmt.Printf("stats- %s \n", statInfos.HostName) + fmt.Printf("stats- %s \n", statInfos.ScnName) + fmt.Printf("stats- %s \n", statInfos.CallId) + fmt.Printf("stats- %s \n", statInfos.TrId) + fmt.Printf("stats- %s \n", statInfos.ConcCall) + fmt.Printf("stats- %s \n", statInfos.SvcType) + fmt.Printf("stats- %s \n", statInfos.SvcReqTime) + fmt.Printf("stats- %s \n", statInfos.SvcRspTime) + fmt.Printf("stats- %s \n", statInfos.ResultMsg) + fmt.Printf("stats- %s \n", statInfos.SttText) + fmt.Printf("stats- %s \n", statInfos.TtsText) + // l.Printf(icslog.LOG_LEVEL_INFO, -1, "Recved Stat Command(%s) %d", ttsHeader, rlen) + } + } +} + +func (statInfos *StatInfos) ChangeByteToString(statInfo []byte) { + // n := bytes.Index(statInfo[STAT_INFO:SEQ_ID], []byte{0}) + statInfos.SeqId = string(statInfo[STAT_INFO:SEQ_ID]) + // fmt.Println("seqid ", statInfo[STAT_INFO : SEQ_ID]) + + // n := bytes.Index(statInfo[SEQ_ID:LOG_TIME], []byte{0}) + statInfos.LogTime = string(statInfo[SEQ_ID:LOG_TIME]) + // fmt.Println("seqid ", statInfo[SEQ_ID : SEQ_ID+n]) + + // n = bytes.Index(statInfo[LOG_TIME:LOG_TYPE], []byte{0}) + statInfos.LogType = string(statInfo[LOG_TIME:LOG_TYPE]) + // fmt.Println("seqid ", statInfo[SEQ_ID : SEQ_ID+n]) + + // n = bytes.Index(statInfo[LOG_TYPE:SID], []byte{0}) + statInfos.Sid = string(statInfo[LOG_TYPE:SID]) + + // n = bytes.Index(statInfo[SID:RESULT_CODE], []byte{0}) + statInfos.ResultCode = string(statInfo[SID:RESULT_CODE]) + + // n = bytes.Index(statInfo[RESULT_CODE:REQ_TIME], []byte{0}) + statInfos.ReqTime = string(statInfo[RESULT_CODE:REQ_TIME]) + + // n = bytes.Index(statInfo[REQ_TIME:RES_TIME], []byte{0}) + statInfos.RspTime = string(statInfo[REQ_TIME:RES_TIME]) + + // n = bytes.Index(statInfo[RES_TIME:CLIENT_IP], []byte{0}) + statInfos.ClientIp = string(statInfo[RES_TIME:CLIENT_IP]) + + // n = bytes.Index(statInfo[CLIENT_IP:DEV_INFO], []byte{0}) + statInfos.DevInfo = string(statInfo[CLIENT_IP:DEV_INFO]) + + // n = bytes.Index(statInfo[DEV_INFO:OS_INFO], []byte{0}) + statInfos.OsInfo = string(statInfo[DEV_INFO:OS_INFO]) + + // n = bytes.Index(statInfo[OS_INFO:NW_INFO], []byte{0}) + statInfos.NwInfo = string(statInfo[OS_INFO:NW_INFO]) + + // n = bytes.Index(statInfo[NW_INFO:SVC_NAME], []byte{0}) + statInfos.SvcName = string(statInfo[NW_INFO:SVC_NAME]) + + // n = bytes.Index(statInfo[SVC_NAME:DEV_MODEL], []byte{0}) + statInfos.DevModel = string(statInfo[SVC_NAME:DEV_MODEL]) + + // n = bytes.Index(statInfo[DEV_MODEL:CARRIER_TYPE], []byte{0}) + statInfos.CarrierType = string(statInfo[DEV_MODEL:CARRIER_TYPE]) + + // n = bytes.Index(statInfo[CARRIER_TYPE:HOST_NAME], []byte{0}) + statInfos.HostName = string(statInfo[CARRIER_TYPE:HOST_NAME]) + + // n = bytes.Index(statInfo[HOST_NAME:SCN_NAME], []byte{0}) + statInfos.ScnName = string(statInfo[HOST_NAME:SCN_NAME]) + + // n = bytes.Index(statInfo[SCN_NAME:CALL_ID], []byte{0}) + statInfos.CallId = string(statInfo[SCN_NAME:CALL_ID]) + + // n = bytes.Index(statInfo[CALL_ID:TR_ID], []byte{0}) + statInfos.TrId = string(statInfo[CALL_ID:TR_ID]) + + // n = bytes.Index(statInfo[TR_ID:CONC_CALL], []byte{0}) + statInfos.ConcCall = string(statInfo[TR_ID:CONC_CALL]) + + // n = bytes.Index(statInfo[CONC_CALL:SVC_TYPE], []byte{0}) + statInfos.SvcType = string(statInfo[CONC_CALL:SVC_TYPE]) + + // n = bytes.Index(statInfo[SVC_TYPE:SVC_REQ_TIME], []byte{0}) + statInfos.SvcReqTime = string(statInfo[SVC_TYPE:SVC_REQ_TIME]) + + // n = bytes.Index(statInfo[SVC_REQ_TIME:SVC_RSP_TIME], []byte{0}) + statInfos.SvcRspTime = string(statInfo[SVC_REQ_TIME:SVC_RSP_TIME]) + + // n = bytes.Index(statInfo[SVC_RSP_TIME:RESULT_MSG], []byte{0}) + statInfos.ResultMsg = string(statInfo[SVC_RSP_TIME:RESULT_MSG]) + + // n = bytes.Index(statInfo[RESULT_MSG:STT_TEXT], []byte{0}) + statInfos.SttText = string(statInfo[RESULT_MSG:STT_TEXT]) + + // n = bytes.Index(statInfo[STT_TEXT:TTS_TEXT], []byte{0}) + statInfos.TtsText = string(statInfo[STT_TEXT:]) + +} diff --git a/icssvc/icssvc.go b/icssvc/icssvc.go new file mode 100644 index 0000000..5904c62 --- /dev/null +++ b/icssvc/icssvc.go @@ -0,0 +1,222 @@ +package icssvc + +import ( + "fmt" + "math" + "os" + "sync" + "time" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icslog" + "gitlab.com/ics_cinnamon/voiceStatistics/icsutil" +) + +const ( + COMPANY_NAME = "iComsys" + VERSION = "1.0.0" + BUILD_DATE = "" +) + +const ( + ONEMB = 1048576 +) + +type IcsService struct { + isExit bool //exit service + isStop bool //pause service + + log *icslog.IcsLog + config *icsconf.IcsConfig + //homeDir string +} + +var ServiceStatus *IcsService +var once sync.Once + +func GetServiceStatus() *IcsService { + once.Do(func() { + ServiceStatus = &IcsService{isExit: false, isStop: false} + }) + return ServiceStatus +} + +func NewService() *IcsService { + return GetServiceStatus() +} + +func (s *IcsService) Exit(start bool) { + i := GetServiceStatus() + i.isExit = start +} + +func (s IcsService) GetExit() bool { + return s.isExit +} + +func (s *IcsService) Stop(stop bool) { + i := GetServiceStatus() + i.isStop = stop +} + +func (s IcsService) GetStop() bool { + return s.isStop +} + +func (s *IcsService) SetIcsConfig(conf *icsconf.IcsConfig) *icserror.IcsError { + if conf == nil { + return icserror.ICSERRInvalidParam + } + s.config = conf + + return nil +} + +func (s IcsService) GetIcsConfig() *icsconf.IcsConfig { + //fmt.Println(s.config) + return s.config +} + +func (s *IcsService) SetIcsLog(log *icslog.IcsLog) { + s.log = log +} + +func (s IcsService) GetIcsLog() (log *icslog.IcsLog) { + return s.log +} + +func (s IcsService) ShowServiceInfo() (info string) { + info = fmt.Sprintf("%s Voice Gateway version %s\nCopyright (C) 2022 %s\n\n", COMPANY_NAME, VERSION, COMPANY_NAME) + fmt.Printf("%s Voice Gateway version %s\nCopyright (C) 2022 %s\n\n", COMPANY_NAME, VERSION, COMPANY_NAME) + + return info +} + +func (s IcsService) getMonth2Int(mon time.Month) int { + switch mon { + case time.January: + return 1 + case time.February: + return 2 + case time.March: + return 3 + case time.April: + return 4 + case time.May: + return 5 + case time.June: + return 6 + case time.July: + return 7 + case time.August: + return 8 + case time.September: + return 9 + case time.October: + return 10 + case time.November: + return 11 + case time.December: + return 12 + } + + return -1 +} + +// func (s IcsService) GetRemainExpire() (int, *icserror.IcsError) { +// if s.config == nil { +// return -1, icserror.ICSERRInvalidParam +// } + +// var rem int + +// currentTime := time.Now() + +// yy := currentTime.Year() +// mm := currentTime.Month() +// intmm := s.getMonth2Int(mm) +// if intmm != -1 { +// expire := s.config.GetExpire() +// //since 2018.01 +// rem = expire - (((yy - 2018) * 12) + intmm) +// } else { +// return -1, icserror.ICSERRSVCTime +// } + +// return rem, nil +// } + +///////////////////////////// +func (s IcsService) LogWatcher() *icserror.IcsError { + l := icslog.GetIcsLog() + l.Print(icslog.LOG_LEVEL_INFO, -1, "Log Watcher Start") + + for !s.GetExit() { + for s.GetStop() { + time.Sleep(time.Millisecond) + } + + //check log file date + // y1, m1, d1 := s.log.CurrentDate.Date() + // h1, mi1 := s.log.CurrentDate.Hour(), s.log.CurrentDate.Minute() + mi1 := s.log.CurrentDate.Minute() + y2, m2, d2 := time.Now().Date() + h2, mi2, ss2 := time.Now().Hour(), time.Now().Minute(), time.Now().Second() + + if h2 == l.DelHour && mi2 == 0 && ss2 == 0 { + go l.DelLog() + time.Sleep(time.Second) + } + + //uplus + times := mi2 - mi1 + rotateTime := math.Abs(float64(times)) + + if rotateTime > 4 { // only 5 minute + s.config = icsconf.GetIcsConfig() + logpath := fmt.Sprintf("%s", s.config.LogConfig.Path) + aSpace := icsutil.GetDiskAvailableSpace(logpath) + if aSpace < uint64(s.config.LogConfig.Disklimit*ONEMB) { + return icserror.ICSERRUTILDiskFull + } + + s.log.M.Lock() + + //save and close old log file + s.log.LogFile.Sync() + s.log.LogFile.Close() + + //create new log file + s.log.CurrentDate = time.Now() + /* + fmt.Println(s.log) + fmt.Println(s.log.LogFileName) + fmt.Println(s.config) + fmt.Println(s.config.GetHomeDir()) + fmt.Println(s.log.Path) + fmt.Println(y2) + fmt.Println(m2) + fmt.Println(d2) + */ + s.log.LogFileName = fmt.Sprintf("%s/icsvs.log-%d%02d%02d.%02d.%02d", s.log.Path, y2, m2, d2, h2, mi2) + var oerr error + s.log.LogFile, oerr = os.OpenFile(s.log.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if oerr != nil { + icserror.ICSERRFileOpen.SetError(oerr) + //icserror.ICSERRFileOpen.PrintWithCaller(1) + + s.log.M.Unlock() + return icserror.ICSERRFileOpen + } + + s.log.M.Unlock() + l.Printf(icslog.LOG_LEVEL_INFO, -1, "Log Watcher: Updated Log File - %s", s.log.LogFileName) + } + + //l.Printf(icslog.LOG_LEVEL_INFO, -1, "Log Watcher") + time.Sleep(time.Millisecond) + } + + return nil +} diff --git a/icssvc/stop.sh b/icssvc/stop.sh new file mode 100644 index 0000000..a3a40fb --- /dev/null +++ b/icssvc/stop.sh @@ -0,0 +1,4 @@ +#!/usr/bin/sh +HOME=$ICSVS_ROOT +`cat $HOME/voicegateway.pid | xargs kill` +echo "VoiceGateway Stoped..." diff --git a/icsutil/daemon.go b/icsutil/daemon.go new file mode 100644 index 0000000..725d701 --- /dev/null +++ b/icsutil/daemon.go @@ -0,0 +1,273 @@ +package icsutil + +import ( + "fmt" + "io/ioutil" + "os" + "os/signal" + "strings" + "syscall" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" +) + +func Deamonize() (int, error) { + pid, _, sysErr := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) + if sysErr != 0 { + //fmt.Println("fail to call fork") + return -1, fmt.Errorf("fail to call fork - %d", sysErr) + } + if pid > 0 { //parent + //return int(pid), nil + //fmt.Printf("Parent PID %d\n", int(pid)) + os.Exit(0) + } else if int(pid) < 0 { + //fmt.Println("child id is incorrect") + return int(pid), fmt.Errorf("child id is incorrect") + } /* else if int(pid) == 0 { //child + p := os.Getpid() + fmt.Printf("Child Process PID %d\n", p) + }*/ + + //p1 := os.Getpid() + //fmt.Printf("Child Process PID %d\n", p1) + + ret, err := syscall.Setsid() + if err != nil || ret < 0 { + //fmt.Println("fail to call setsid", pid, err) + return int(pid), fmt.Errorf("fail to call setsid") + } + + signal.Ignore(syscall.SIGHUP) + syscall.Umask(0) + + conf := icsconf.GetIcsConfig() + homeDir := conf.GetHomeDir() + cmdline := fmt.Sprintf("%s/bin/voicegateway", homeDir) + attr := &os.ProcAttr{Env: os.Environ()} + p, perr := os.StartProcess(cmdline, []string{""}, attr) + if perr != nil { + return -1, perr + } + + if werr := WritePID(p.Pid); werr != nil { + fmt.Println("Error Write PID :", werr) + } + + return p.Pid, nil +} + +func CloseSTDIO() { + for iter := 0; iter < 3; iter++ { + syscall.Close(iter) + } +} + +func WritePID(pid int) *icserror.IcsError { + isStop := false + var homeDir string + for _, e := range os.Environ() { + s := strings.SplitN(e, "=", 2) + if strings.Compare(s[0], "ICSVS_ROOT") == 0 { + homeDir = s[1] + //service.SetHomeDir(s[1]) + isStop = true + break + } + } + + if isStop { + pidFilename := fmt.Sprintf("%s/voiceStastics.pid", homeDir) + spid := fmt.Sprintf("%d", pid) + ioutil.WriteFile(pidFilename, []byte(spid), 0666) + } else { + return icserror.ICSERRNotFoundHome + } + + return nil +} + +func CheckPID() bool { + isStop := false + var homeDir string + for _, e := range os.Environ() { + s := strings.SplitN(e, "=", 2) + if strings.Compare(s[0], "ICSVS_ROOT") == 0 { + homeDir = s[1] + //service.SetHomeDir(s[1]) + isStop = true + break + } + } + + if isStop { + pidFilename := fmt.Sprintf("%s/voicegateway.pid", homeDir) + fd, err := os.Open(pidFilename) + if err != nil { + fd.Close() + return false + } + pid := make([]byte, 12) + rlen, rerr := fd.Read(pid) + if rerr != nil { + return false + } + fd.Close() + + cmdline := fmt.Sprintf("/proc/%s/exe", string(pid[:rlen])) + //cmdline := fmt.Sprintf("/proc/%s/cmdline", string(pid[:rlen])) + /* + cfd, cerr := os.Open(cmdline) + if cerr != nil { + cfd.Close() + return false + } + pname := make([]byte, 128) + rlen, rerr = cfd.Read(pname) + if rerr != nil { + return false + } + cfd.Close() + */ + pname, rlerr := os.Readlink(cmdline) + if rlerr != nil { + return false + } + + //fmt.Println(pname) + + if strings.Contains(pname, "voicegateway") { + return true + } + } + + return false +} + +// Process Check +const PNAMEC = "voicegatewayCheck" + +func DeamonizeProcessCheck() (int, error) { + pid, _, sysErr := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) + if sysErr != 0 { + //fmt.Println("fail to call fork") + return -1, fmt.Errorf("fail to call fork - %d", sysErr) + } + if pid > 0 { //parent + //return int(pid), nil + //fmt.Printf("Child Process Created %d\n", int(pid)) + os.Exit(0) + } else if int(pid) < 0 { + //fmt.Println("child id is incorrect") + return int(pid), fmt.Errorf("child id is incorrect") + } /* else if int(pid) == 0 { //child + p := os.Getpid() + fmt.Printf("Child Process PID %d\n", p) + }*/ + + ret, err := syscall.Setsid() + if err != nil || ret < 0 { + //fmt.Println("fail to call setsid", pid, err) + return int(pid), fmt.Errorf("Fail to call setsid") + } + + signal.Ignore(syscall.SIGHUP) + syscall.Umask(0) + + conf := icsconf.GetIcsConfig() + homeDir := conf.GetHomeDir() + cmdline := fmt.Sprintf("%s/bin/%s", homeDir, PNAMEC) + attr := &os.ProcAttr{Env: os.Environ()} + p, perr := os.StartProcess(cmdline, []string{""}, attr) + if perr != nil { + return -1, perr + } + + if werr := PWritePID(p.Pid); werr != nil { + fmt.Println("Error PWrite PID :", werr) + } + + return p.Pid, nil +} + +func PWritePID(pid int) *icserror.IcsError { + isStop := false + var homeDir string + for _, e := range os.Environ() { + s := strings.SplitN(e, "=", 2) + if strings.Compare(s[0], "ICSVS_ROOT") == 0 { + homeDir = s[1] + //service.SetHomeDir(s[1]) + isStop = true + break + } + } + + if isStop { + pidFilename := fmt.Sprintf("%s/voicegatewayCheck.pid", homeDir) + spid := fmt.Sprintf("%d", pid) + ioutil.WriteFile(pidFilename, []byte(spid), 0666) + } else { + return icserror.ICSERRNotFoundHome + } + + return nil +} + +func PCheckPID() bool { + isStop := false + var homeDir string + for _, e := range os.Environ() { + s := strings.SplitN(e, "=", 2) + if strings.Compare(s[0], "ICSVS_ROOT") == 0 { + homeDir = s[1] + //service.SetHomeDir(s[1]) + isStop = true + break + } + } + + if isStop { + pidFilename := fmt.Sprintf("%s/voicegatewayP.pid", homeDir) + fd, err := os.Open(pidFilename) + if err != nil { + fd.Close() + return false + } + pid := make([]byte, 12) + rlen, rerr := fd.Read(pid) + if rerr != nil { + return false + } + fd.Close() + + cmdline := fmt.Sprintf("/proc/%s/exe", string(pid[:rlen])) + //cmdline := fmt.Sprintf("/proc/%s/cmdline", string(pid[:rlen])) + /* + cfd, cerr := os.Open(cmdline) + if cerr != nil { + cfd.Close() + return false + } + pname := make([]byte, 128) + rlen, rerr = cfd.Read(pname) + if rerr != nil { + return false + } + cfd.Close() + */ + pname, rlerr := os.Readlink(cmdline) + if rlerr != nil { + return false + } + + fmt.Println(pname) + + if strings.Contains(pname, PNAMEC) { + return true + } + } + + return false +} diff --git a/icsutil/util.go b/icsutil/util.go new file mode 100644 index 0000000..6582e70 --- /dev/null +++ b/icsutil/util.go @@ -0,0 +1,38 @@ +package icsutil + +import ( + "fmt" + "runtime" + "strings" + "os" + + "golang.org/x/sys/unix" +) + +func PrintCallTrace(depth int, v interface{}) { + funcname, file, line, ok := runtime.Caller(depth) + if ok { + files := strings.Split(file, "/") + fileslen := len(files) + func1 := runtime.FuncForPC(funcname).Name() + funcs := strings.Split(func1, "/") + funcslen := len(funcs) + + fmt.Printf("[%s:%d %s] %v\n", files[fileslen-1], line, funcs[funcslen-1], v) + } +} + +func GetDiskAvailableSpace(path string) uint64 { + var stat unix.Statfs_t + unix.Statfs(path, &stat) + return stat.Bavail * uint64(stat.Bsize) +} + +func DeleteFile(path string, filename string) string { + var err string + rmerr := os.Remove(fmt.Sprintf("%s/%s", path, filename)) + if rmerr != nil { + fmt.Printf("Delete File error - %s\n", rmerr) + } + return err +} \ No newline at end of file diff --git a/icsvg.xml b/icsvg.xml new file mode 100644 index 0000000..51225ba --- /dev/null +++ b/icsvg.xml @@ -0,0 +1,76 @@ + + + + iCOMSYS_CALLAGENT + icsvs001 + 00001 + 00 + 192.168.0.21 + + + 2CF05DD7C692 + 8 + 9999 + + + /home/leejj9612/dev/logs/icsvs + 100 + DEBUG2 + file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 192.168.0.21 + + diff --git a/loader/loader b/loader/loader new file mode 100755 index 0000000..1f1173a Binary files /dev/null and b/loader/loader differ diff --git a/loader/loader.go b/loader/loader.go new file mode 100644 index 0000000..649a0a0 --- /dev/null +++ b/loader/loader.go @@ -0,0 +1,68 @@ +package main + +import ( + "fmt" + "os" + "strings" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icslog" + "gitlab.com/ics_cinnamon/voiceStatistics/icsutil" +) + +func main() { + if icsutil.CheckPID() { + fmt.Println("VoiceGateway Already Running. Terminating...") + os.Exit(0) + } + + //get Voice Gateway home dir + isStop := false + var homeDir string + for _, e := range os.Environ() { + s := strings.SplitN(e, "=", 2) + if strings.Compare(s[0], "ICSVS_ROOT") == 0 { + homeDir = s[1] + //service.SetHomeDir(s[1]) + isStop = true + break + } + } + if !isStop { + icserror.ICSERRNotFoundHome.PrintWithCaller(1) + return + } + + //configuration + configFile := fmt.Sprintf("%s/config/icsvs.xml", homeDir) + conf, confErr := icsconf.OpenConfig(configFile, homeDir) + if confErr != nil { + confErr.PrintWithCaller(0) + fmt.Println(confErr.GetError()) + return + } + + icsLog, lerr := icslog.NewIcsLog( + &conf.LogConfig, + icslog.GetLogLevelID(conf.LogConfig.Level), + icslog.GetLogOutputID(conf.LogConfig.Output), + conf.LogConfig.Path, + conf.LogConfig.Disklimit, + ) + if lerr != nil { + lerr.PrintWithCaller(0) + } + + icsLog.Print(icslog.LOG_LEVEL_INFO, -1, "Started VoiceGateway Loader") + + //deamonize + pid, derr := icsutil.DeamonizeProcessCheck() + if derr != nil { + icserror.ICSERRDeamonize.SetError(derr) + icsLog.Printf(icslog.LOG_LEVEL_ERROR, -1, "VoiceGateway : %s", icserror.ICSERRDeamonize.GetError()) + os.Exit(0) + } + + icsLog.Printf(icslog.LOG_LEVEL_INFO, -1, "Loaded VoiceGateway[%d]", pid) +} diff --git a/voicegatewayCheck/voicegatewayCheck b/voicegatewayCheck/voicegatewayCheck new file mode 100755 index 0000000..5a18e7e Binary files /dev/null and b/voicegatewayCheck/voicegatewayCheck differ diff --git a/voicegatewayCheck/voicegatewayCheck.go b/voicegatewayCheck/voicegatewayCheck.go new file mode 100644 index 0000000..97892c5 --- /dev/null +++ b/voicegatewayCheck/voicegatewayCheck.go @@ -0,0 +1,120 @@ +package main + +import ( + "fmt" + "os" + "os/signal" + "strings" + "sync" + "time" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icslog" + "gitlab.com/ics_cinnamon/voiceStatistics/icsutil" +) + +var wg sync.WaitGroup + +func main() { + var homeDir string + + //get Voice Agent home dir + isStop := false + + for _, e := range os.Environ() { + s := strings.SplitN(e, "=", 2) + if strings.Compare(s[0], "ICSVS_ROOT") == 0 { + homeDir = s[1] + //service.SetHomeDir(s[1]) + isStop = true + break + } + } + if !isStop { + icserror.ICSERRNotFoundHome.PrintWithCaller(1) + return + } + + //configuration + configFile := fmt.Sprintf("%s/config/icsvs.xml", homeDir) + //configFile := fmt.Sprintf("%s/config/icsvc.xml", service.GetHomeDir()) + //fmt.Println("Config file:", configFile) + conf, confErr := icsconf.OpenConfig(configFile, homeDir) + if confErr != nil { + confErr.PrintWithCaller(0) + return + } + + icsLog, lerr := icslog.NewIcsLog( + &conf.LogConfig, + icslog.GetLogLevelID(conf.LogConfig.Level), + icslog.GetLogOutputID(conf.LogConfig.Output), + conf.LogConfig.Path, + conf.LogConfig.Disklimit, + ) + if lerr != nil { + lerr.PrintWithCaller(0) + } + + for { + // log file name change + y1, m1, d1 := icsLog.CurrentDate.Date() + y2, m2, d2 := time.Now().Date() + + if d1 != d2 || y1 != y2 || m1 != m2 { + icsLog.M.Lock() + icsLog.LogFileName = fmt.Sprintf("%s/icsvs.log-%d%02d%02d", icsLog.Path, y2, m2, d2) // file name change + var oerr error + icsLog.LogFile, oerr = os.OpenFile(icsLog.LogFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if oerr != nil { + icserror.ICSERRFileOpen.SetError(oerr) + icsLog.M.Unlock() + } + icsLog.M.Unlock() + } + + if icsutil.CheckPID() { + // icsLog.Print(icslog.LOG_LEVEL_INFO, -1, "Voice Agent HealthCheck") + } else { + ProcessLoad(icsLog) + ListenDieSignal() + + // icsLog.Print(icslog.LOG_LEVEL_INFO, -1, "Voice Gateway Death - reloading...") + + // icsLog.Print(icslog.LOG_LEVEL_INFO, -1, "Started Voice Gateway Loader") + + // //deamonize + // pid, derr := icsutil.Deamonize() + // if derr != nil { + // icserror.ICSERRDeamonize.SetError(derr) + // icsLog.Printf(icslog.LOG_LEVEL_ERROR, -1, "voicegateway: %s", icserror.ICSERRDeamonize.GetError()) + // os.Exit(0) + // } + + // icsLog.Printf(icslog.LOG_LEVEL_INFO, -1, "Loaded Voice Gateway[%d]", pid) + } + } + +} + +func ListenDieSignal() { + stop := make(chan os.Signal) + signal.Notify(stop, os.Interrupt) + fmt.Println("Listen Dying signal started") + + <-stop + fmt.Println("stopped") + wg.Done() +} + +func ProcessLoad(l *icslog.IcsLog) (int, error) { + pid, derr := icsutil.Deamonize() + if derr != nil { + icserror.ICSERRDeamonize.SetError(derr) + l.Printf(icslog.LOG_LEVEL_ERROR, -1, "voicegateway: %s", icserror.ICSERRDeamonize.GetError()) + return 0, derr + } + l.Printf(icslog.LOG_LEVEL_INFO, -1, "Loaded Voice Gateway[%d]", pid) + return pid, nil +} diff --git a/voicestatistics.go b/voicestatistics.go new file mode 100644 index 0000000..6baee2f --- /dev/null +++ b/voicestatistics.go @@ -0,0 +1,140 @@ +package main + +// #cgo LDFLAGS: -L/usr/local/lib /usr/local/lib/libavcodec.a /usr/local/lib/libavformat.a /usr/local/lib/llibavutil.a /usr/local/lib/llibswscale.a -llibswresample.a -llibavdevice -llibavfilter + +import ( + "fmt" + "os" + "strings" + + "gitlab.com/ics_cinnamon/voiceStatistics/icsapp" + "gitlab.com/ics_cinnamon/voiceStatistics/icsconf" + "gitlab.com/ics_cinnamon/voiceStatistics/icserror" + "gitlab.com/ics_cinnamon/voiceStatistics/icslog" + "gitlab.com/ics_cinnamon/voiceStatistics/icssvc" + "gitlab.com/ics_cinnamon/voiceStatistics/icsutil" +) + +func main() { + service := icssvc.NewService() + + /////////////////////////////////// + //Demonize service + //check Voice Gateway pid file - ICSVS_ROOT/voicegateway.pid + //if already running, terminate self. + /* + if icsutil.CheckPID() { + service.ShowServiceInfo() + fmt.Println("Voice Gateway Already Running. Terminating...") + os.Exit(0) + } + */ + + /* + //deamonize + pid, derr := icsutil.Deamonize() + if derr != nil { + service.ShowServiceInfo() + icserror.ICSERRDeamonize.SetError(derr) + fmt.Println("voice Gateway:", icserror.ICSERRDeamonize) + os.Exit(0) + return + } + fmt.Println("PID", pid) + */ //////////////////////// + + //get Voice Gateway home dir + isStop := false + var homeDir string + for _, e := range os.Environ() { + s := strings.SplitN(e, "=", 2) + if strings.Compare(s[0], "ICSVS_ROOT") == 0 { + homeDir = s[1] + //service.SetHomeDir(s[1]) + isStop = true + break + } + } + if !isStop { + icserror.ICSERRNotFoundHome.PrintWithCaller(1) + return + } + + //configuration + configFile := fmt.Sprintf("%s/config/icsvs.xml", homeDir) + conf, confErr := icsconf.OpenConfig(configFile, homeDir) + if confErr != nil { + confErr.PrintWithCaller(0) + return + } + if confErr := service.SetIcsConfig(conf); confErr != nil { + confErr.PrintWithCaller(0) + } + + icsLog, lerr := icslog.NewIcsLog( + &conf.LogConfig, + icslog.GetLogLevelID(conf.LogConfig.Level), + icslog.GetLogOutputID(conf.LogConfig.Output), + conf.LogConfig.Path, + conf.LogConfig.Disklimit, + ) + if lerr != nil { + lerr.PrintWithCaller(0) + } + + service.SetIcsLog(icsLog) + //create log watcher + go service.LogWatcher() + + info := service.ShowServiceInfo() + info += fmt.Sprintf("iComsys Voice Statistics Home: %s\n", homeDir) + fmt.Printf("iComsys Voice Statistics Home: %s\n", homeDir) + //wd, err := os.Getwd() + logpath := conf.LogConfig.Path + info += fmt.Sprintf("Available Disk Space [%s]: %d MB\n", logpath, icsutil.GetDiskAvailableSpace(logpath)/1024/1024) + fmt.Printf("Available Disk Space [%s]: %d MB\n", logpath, icsutil.GetDiskAvailableSpace(logpath)/1024/1024) + info += conf.ShowConfig() + + //check license expiration + //fmt.Println("Remain Expiration Months:", conf.GetRemainExpire()) + + app := icsapp.Init(conf) + //fmt.Printf("Service Started - %d\n================================\n", pid) + + info = "\n" + info + icsLog.Print(icslog.LOG_LEVEL_INFO, -1, info) + icsLog.Print(icslog.LOG_LEVEL_INFO, -1, "Service Started") + icsLog.Print(icslog.LOG_LEVEL_INFO, -1, "================================") + + ///////////////////////////////// + //icsutil.CloseSTDIO() + ///////////////////////////////// + + execerr := app.Execute() + if execerr != nil { + execerr.PrintWithCaller(1) + os.Exit(1) + } + + /* + deviceName := conf.GetDeviceName() + pcap := icspcap.New() + //pcap.SetFilter("") + packetSource, pcapErr := pcap.Init(deviceName) + //packetSource, icserr := pcap.Init("wlp1s0") + if pcapErr != nil { + if pcapErr.Equal(icserror.ICSERRPCAPOpenLive) { + fmt.Printf("Device Name: %s\n", deviceName) + } + pcapErr.Print() + return + } + fmt.Println("Filter:", pcap.GetFilter()) + + if err := pcap.Run(packetSource); err != nil { + err.Print() + } + defer pcap.Close() + */ + +}