first init

main
jjLee 3 years ago
parent 686e8ffcaa
commit cefde9c745

Binary file not shown.

@ -0,0 +1,12 @@
module gitlab.com/ics_cinnamon/voicegateway
go 1.16
require (
github.com/google/uuid v1.3.0 // indirect
github.com/mitchellh/panicwrap v1.0.0 // indirect
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
)

@ -0,0 +1,28 @@
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/mitchellh/panicwrap v1.0.0 h1:67zIyVakCIvcs69A0FGfZjBdPleaonSgGlXRSRlb6fE=
github.com/mitchellh/panicwrap v1.0.0/go.mod h1:pKvZHwWrZowLUzftuFq7coarnxbBXU4aQh3N0BJOeeA=
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.24 h1:MQlMxeJ5ZBEerHzHf1D+/ruTeA1YXJKL5XbJdI3NVf4=
gitlab.com/ics_cinnamon/joy4 v1.0.24/go.mod h1:LFfF6nA92KMmd/hrGEgQzkIsX/n+IlqCI8vbY8/NnNI=
gitlab.com/ics_cinnamon/joy4 v1.0.25 h1:e20ciX68hnLv50GVENWDeyYkKz0XiX6ALevQfeSfrQc=
gitlab.com/ics_cinnamon/joy4 v1.0.25/go.mod h1:LFfF6nA92KMmd/hrGEgQzkIsX/n+IlqCI8vbY8/NnNI=
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=

@ -0,0 +1,93 @@
package icsapp
import (
"strings"
"time"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icssessionmanager"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
)
type IcsExec struct {
service *icssvc.IcsService
config *icsconf.IcsConfig
//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()
for !exe.service.GetExit() {
for exe.service.GetStop() {
time.Sleep(time.Millisecond)
}
//init session manager and run session, listen SIP port
sm := icssessionmanager.NewSessionManager()
if sm == nil {
l.Print(icslog.LOG_LEVEL_FATAL, -1, "Could not init Session Manager!!!")
return icserror.ICSERRSVCInit
}
sm.Load()
///////////////////////////////
//start sip processor
smDone := make(chan *icserror.IcsError)
go func() {
smErr := sm.Run()
if smErr != nil {
smDone <- smErr
return
}
defer sm.Close()
//smDone <- nil
}()
/////////////////////////////////////////////////////////////////////
//start bot-command TCP listener
cmdDone := make(chan *icserror.IcsError)
bcValue := strings.ToUpper(exe.config.CommandConfig.Value)
if strings.Compare("TRUE", bcValue) == 0 {
go func() {
cmdErr := sm.RunBotCommandMNG()
if cmdErr != nil {
cmdDone <- cmdErr
return
}
//defer sm.Close()
//cmdDone <- nil
}()
}
select {
case err := <-smDone:
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Closed SessionManager: %s", err)
if err != nil {
//err.Print()
return err
}
case err := <-cmdDone:
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Closed BotCommand manager: %s", err)
if err != nil {
//err.Print()
return err
}
}
}
return nil
}

@ -0,0 +1,45 @@
//icomsys callback timer
package icscbtimer
import (
"time"
)
type IcsCBTimerFunc func(t *IcsCBTimer)
type IcsCBTimer struct {
ticker *time.Ticker
d time.Duration
cbfunc IcsCBTimerFunc
}
func NewCBTimer(d time.Duration, callbackfunc IcsCBTimerFunc) *IcsCBTimer {
if d <= 0 || callbackfunc == nil {
return nil
}
it := IcsCBTimer{d: d, cbfunc: callbackfunc}
return &it
}
func (t IcsCBTimer) GetTick() <-chan time.Time {
return t.ticker.C
}
func (t *IcsCBTimer) Start() {
if t == nil {
return
}
t.ticker = time.NewTicker(t.d)
go t.cbfunc(t)
}
func (t *IcsCBTimer) Stop() {
if t == nil || t.ticker == nil {
return
}
t.ticker.Stop()
}

@ -0,0 +1,535 @@
package icsconf
import (
"encoding/xml"
"fmt"
"os"
"strings"
"sync"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
)
type IcsConfig struct {
XMLName xml.Name `xml:"ICSVG"`
Version string `xml:"version,attr"`
InfoConfig InfoConfig `xml:"INFO"`
LicenseConfig LicenseConfig `xml:"LICENSE"`
LogConfig LogConfig `xml:"LOG"`
CommandConfig CommandConfig `xml:"COMMAND"`
CallEventConfig CallEventConfig `xml:"CALLEVENT"`
SIPConfig SIPConfig `xml:"SIP"`
AgentConfig []AgentConfig `xml:"AGENT"`
VoiceAgentConfig VoiceAgentConfig `xml:"VOICEAGENT"`
PbxConfig PbxConfig `xml:"PBX"`
SimLoopCount int `xml:"SIMLOOP"`
HomeDir string
}
type InfoConfig struct {
Product string `xml:"PRODUCT"`
TenentID string `xml:"TENENTID"`
ServerID int `xml:"SERVERID"`
ServerIP string `xml:"SERVERIP"`
}
type LicenseConfig struct {
Key string `xml:"KEY"`
Channels int `xml:"CHANNELS"`
Expire int `xml:"EXPIRE"`
}
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"`
}
type CommandConfig struct {
Value string `xml:"value,attr"`
Transport string `xml:"transport,attr"`
Port int `xml:"port,attr"`
}
type AgentConfig struct {
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
RegisterConfig RegisterConfig `xml:"REGISTER"`
OptionsConfig OptionsConfig `xml:"OPTIONS"`
MediaConfig MediaConfig `xml:"MEDIA"`
}
type RegisterConfig struct {
RegisterValue string `xml:"value,attr"`
RegisterTransport string `xml:"transport,attr"`
RegisterExpire int `xml:"expire,attr"`
RegisterUserName string `xml:"username,attr"`
}
type OptionsConfig struct {
OptionsValue string `xml:"value,attr"`
OptionsInterval int `xml:"interval,attr"`
}
type MediaConfig struct {
Media string `xml:"m,attr"`
Port int `xml:"port,attr"`
Format string `xml:"format,attr"`
}
type CallEventConfig struct {
Value string `xml:"value,attr"`
Production string `xml:"production,attr"`
Version string `xml:"version,attr"`
}
type SIPConfig struct {
Value string `xml:"value,attr"`
Transport string `xml:"transport,attr"`
Port int `xml:"port,attr"`
SIPProxy string `xml:"proxy,attr"`
}
type PbxConfig struct {
PbxIp string `xml:"IP"`
PbxPort int `xml:"PORT"`
}
type VoiceAgentConfig struct {
AgentInfo []AgentInfo `xml:"AGENT"`
MyAddr MyAddr `xml:"SERVER"`
}
type AgentInfo struct {
Name string `xml:"name,attr"`
Action string `xml:"action,attr"`
Port int `xml:"port,attr"`
VoicePort int `xml:"voiceport,attr"`
IP string `xml:"ip,attr"`
}
type MyAddr struct {
ServerPort int `xml:"port,attr"`
BasePort int `xml:"baseport,attr"`
PortRange int `xml:"range,attr"`
ServerIP string `xml:",chardata"`
}
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) GetChannelNum() int {
return c.LicenseConfig.Channels
}
func (c IcsConfig) GetExpire() int {
return c.LicenseConfig.Expire
}
func (c IcsConfig) GetPbxIp() string {
return c.PbxConfig.PbxIp
}
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
}
func (c IcsConfig) GetServerIP() string {
return c.VoiceAgentConfig.MyAddr.ServerIP
}
//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("Licensed Channel number : %d\n", c.LicenseConfig.Channels)
agentlen := len(c.VoiceAgentConfig.AgentInfo)
for iter1 := 0; iter1 < agentlen; iter1++ {
fmt.Printf("Voice Agent [%s] %s:%d|%d action: %s\n",
c.VoiceAgentConfig.AgentInfo[iter1].Name,
c.VoiceAgentConfig.AgentInfo[iter1].IP,
c.VoiceAgentConfig.AgentInfo[iter1].Port,
c.VoiceAgentConfig.AgentInfo[iter1].VoicePort,
c.VoiceAgentConfig.AgentInfo[iter1].Action)
}
fmt.Printf("PBX Address : %s:%d\n\n", c.PbxConfig.PbxIp, c.PbxConfig.PbxPort)
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("CallEvent Value: %s\n", c.CallEventConfig.Value)
fmt.Printf("CallEvent Production: %s\n", c.CallEventConfig.Production)
fmt.Printf("CallEvent Version: %s\n", c.CallEventConfig.Version)
fmt.Printf("Log Del Day : %d\n", c.LogConfig.DelConfig.DelDay)
fmt.Printf("Log Del Hour : %d\n", c.LogConfig.DelConfig.DelHour)
fmt.Printf("SIP Value: %s\n", c.SIPConfig.Value)
fmt.Printf("SIP Transport: %s\n", c.SIPConfig.Transport)
fmt.Printf("SIP Port: %d\n", c.SIPConfig.Port)
fmt.Printf("SIP Proxy: %s\n\n", c.SIPConfig.SIPProxy)
/*
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("Licensed Channel number : %d\n", c.LicenseConfig.Channels)
/*
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("PBX Address : %s:%d\n\n", c.PbxConfig.PbxIp, c.PbxConfig.PbxPort)
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)
confmsg += fmt.Sprintf("CallEvent Production: %s\n", c.CallEventConfig.Production)
confmsg += fmt.Sprintf("CallEvent Version: %s\n", c.CallEventConfig.Version)
confmsg += fmt.Sprintf("SIP Transport: %s\n", c.SIPConfig.Transport)
confmsg += fmt.Sprintf("SIP Port: %d\n", c.SIPConfig.Port)
confmsg += fmt.Sprintf("SIP Proxy: %s\n", c.SIPConfig.SIPProxy)
for iter := 0; iter < len(c.AgentConfig); iter++ {
confmsg += fmt.Sprintf("=========================\nAgent Name: %s, Use? %s\n", c.AgentConfig[iter].Name, c.AgentConfig[iter].Value)
confmsg += fmt.Sprintf("Agent Media media: %s\n", c.AgentConfig[iter].MediaConfig.Media)
confmsg += fmt.Sprintf("Agent Media Port: %d\n", c.AgentConfig[iter].MediaConfig.Port)
confmsg += fmt.Sprintf("Agent Media Format: %s\n", c.AgentConfig[iter].MediaConfig.Format)
confmsg += fmt.Sprintf("Register value: %s\n", c.AgentConfig[iter].RegisterConfig.RegisterValue)
confmsg += fmt.Sprintf("Register Transport: %s\n", c.AgentConfig[iter].RegisterConfig.RegisterTransport)
confmsg += fmt.Sprintf("Register Expire: %d\n", c.AgentConfig[iter].RegisterConfig.RegisterExpire)
confmsg += fmt.Sprintf("Register Username: %s\n\n", c.AgentConfig[iter].RegisterConfig.RegisterUserName)
}
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
}

@ -0,0 +1,13 @@
package icsconf
import (
"fmt"
"testing"
)
func TestGetModName(t *testing.T) {
conf, _ := OpenConfig("/Users/changsoolee/repository/voicegateway/icsvg.xml", "/home/icsvg")
fmt.Println(conf.LicenseConfig)
fmt.Println(conf.PbxConfig)
}

@ -0,0 +1,132 @@
package icsdtmf
import (
"encoding/binary"
"fmt"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)
type ICSDTMF struct {
rfc2833 *RFC2833
}
func NewICSDTMF() *ICSDTMF {
d := ICSDTMF{rfc2833: nil}
return &d
}
func DTMF(dtmf *ICSDTMF, data interface{}, pcm []byte) (string, *icserror.IcsError) {
switch v := (data).(type) {
case icspacketparser.RTP:
rtp := v
switch rtp.GetPayloadType() { //in band
case icspacketparser.DTMF101: //rtp 101
//fmt.Println("101")
rfc2833, d, derr := dtmfRFC2833(rtp)
if rfc2833.Mark { //if rtp mark, reset old dtmf handle
dtmf.rfc2833 = nil
return "", icserror.ICSERRDTMFCont
}
if derr != icserror.ICSERRDTMFCont {
if dtmf.rfc2833 == nil || !dtmf.rfc2833.isEqual(rfc2833) {
dtmf.rfc2833 = rfc2833
dtmf := fmt.Sprintf("%d", d)
return dtmf, derr
} else {
return "", icserror.ICSERRDTMFCont
}
} else {
return "", derr
}
case icspacketparser.PCMA:
fallthrough
case icspacketparser.G729:
fallthrough
case icspacketparser.PCMU: //bypass
dtmfBypass(pcm)
}
case icspacketparser.SIP: //sip info. rfc2976
}
return "", icserror.ICSERRDTMFFail
}
func (d *ICSDTMF) Reset() {
d.rfc2833 = nil
}
///////////////////////////////////////////////////////////////////////
//RFC 2833 - rtp event
type RFC2833 struct {
Event int
End bool
Volume int
Duration int
Mark bool
}
func dtmfRFC2833(rtp icspacketparser.RTP) (*RFC2833, int, *icserror.IcsError) {
r, err := parseRFC2833(rtp)
if err == icserror.ICSERRDTMFFail {
return nil, -1, err
} else if err == icserror.ICSERRDTMFCont {
return r, -1, err
}
event, err := r.GetDTMF()
return r, event, err
}
func parseRFC2833(rtp icspacketparser.RTP) (*RFC2833, *icserror.IcsError) {
r := RFC2833{}
data := rtp.Payload
r.End = data[1]&0x80 == 0x80
if r.End {
//fmt.Println("RTP Event End?", r.End, data[1], len(data))
r.Event = int(data[0])
//fmt.Println("DTMF :", r.Event)
vol := data[1] << 2
r.Volume = int(vol >> 2)
//fmt.Println("vol", r.Volume, vol, data[1])
dur := binary.BigEndian.Uint16(data[2:])
r.Duration = int(dur)
//fmt.Println("Dur", dur)
} else {
r.Mark = rtp.Mark
return &r, icserror.ICSERRDTMFCont
}
r.Mark = rtp.Mark
return &r, icserror.ICSERRDTMFOK
}
func (r RFC2833) GetDTMF() (int, *icserror.IcsError) {
return r.Event, icserror.ICSERRDTMFOK
}
func (r RFC2833) isEqual(rfc2833 *RFC2833) bool {
if r.Duration == rfc2833.Duration && r.End == rfc2833.End && r.Event == rfc2833.Event && r.Volume == rfc2833.Volume {
return true
}
return false
}
///////////////////////////////////////////////////////////////////////
//bypass - audio
type ByPassDTMF struct {
VoiceBuf []byte
}
func dtmfBypass(data []byte) (string, *icserror.IcsError) {
return "", icserror.ICSERRDTMFFail
}

@ -0,0 +1,38 @@
package rms
import (
"encoding/binary"
"math"
)
func RMS(voicedata []byte) float64 {
var rms, sum, average float64
rms = 0.0
sum = 0.0
length := len(voicedata)
if length <= 0 {
return 0.0
}
length /= 2
for iter := 0; iter < length; iter++ {
uval := binary.LittleEndian.Uint16(voicedata[iter*2 : iter*2+2])
sval := int16(uval)
pval := math.Pow(float64(sval), 2)
sum += pval
}
average = sum / float64(length)
/*
for iter := 0; iter < length; iter++ {
summs += math.Pow(float64(voicedata[iter])-average, float64(2))
}
avgms = summs / float64(length)
*/
rms = math.Sqrt(average)
return rms
}

@ -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
}

@ -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")
}

@ -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)
)

@ -0,0 +1,90 @@
package icsevent
import (
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/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
}

@ -0,0 +1,55 @@
package icsevent
import (
"fmt"
"testing"
"gitlab.com/ics_cinnamon/voicegateway/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)
}
}

@ -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/voicegateway/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]
}

@ -0,0 +1,118 @@
/*
****************************
struct EventSystem
****************************
session Job queue
Event struct Event ID JobQ .
*/
package icsevent
import (
"sync"
"gitlab.com/ics_cinnamon/voicegateway/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
}

@ -0,0 +1,298 @@
package icslog
import (
"bytes"
"fmt"
"log"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"io/ioutil"
"runtime/debug"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icsutil"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
)
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/icsvg.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)
}

@ -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
}

@ -0,0 +1,185 @@
package icslog
import (
"fmt"
"os"
"path/filepath"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/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()
}
}

@ -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
}

@ -0,0 +1,262 @@
package icsmediaconv
import (
"fmt"
"sync"
"gitlab.com/ics_cinnamon/joy4/av"
"gitlab.com/ics_cinnamon/joy4/cgo/ffmpeg"
"gitlab.com/ics_cinnamon/joy4/codec"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)
const (
ICS_PT_MULAW = 0
ICS_PT_ALAW = 8
ICS_PT_G729 = 18
ICS_PT_END = ICS_PT_G729
)
const PCM_8K_16BIT_10MS_SIZE = 160
type Converter struct {
payloadtype icspacketparser.PayloadType
codec av.AudioCodecData
name string
decoder *ffmpeg.AudioDecoder
encoder *ffmpeg.AudioEncoder
samplingRate int
onePacketSize int
//frame *av.AudioFrame
isStart bool
m *sync.Mutex
ID int
}
func NewConverter(id int, pt icspacketparser.PayloadType, dec bool) (*Converter, *icserror.IcsError) {
conv := &Converter{payloadtype: pt}
conv.ID = id
conv.isStart = false
conv.m = &sync.Mutex{}
if dec { //decoding
switch pt {
case ICS_PT_MULAW:
conv.codec = codec.NewPCMMulawCodecData()
conv.samplingRate = 8000
conv.onePacketSize = 80
//conv.onePacketSize = 160
case ICS_PT_ALAW:
conv.codec = codec.NewPCMAlawCodecData()
conv.samplingRate = 8000
conv.onePacketSize = 80
//conv.onePacketSize = 160
case ICS_PT_G729:
conv.codec = codec.NewG729CodecData()
conv.samplingRate = 8000
conv.onePacketSize = 10
default:
return nil, icserror.ICSERRCONVNotSupportedCodec
}
var err error
conv.decoder, err = ffmpeg.NewAudioDecoder(conv.codec)
if err != nil {
icserror.ICSERRCONVNotSupportedCodec.SetError(err)
return nil, icserror.ICSERRCONVNotSupportedCodec
}
} else { //encoding
switch pt {
case ICS_PT_MULAW:
conv.codec = codec.NewPCMMulawCodecData()
conv.name = "mulaw"
conv.samplingRate = 8000
conv.onePacketSize = 160
case ICS_PT_ALAW:
conv.codec = codec.NewPCMAlawCodecData()
conv.name = "alaw"
conv.samplingRate = 8000
conv.onePacketSize = 160
case ICS_PT_G729:
conv.codec = codec.NewG729CodecData()
conv.name = "g729"
conv.samplingRate = 8000
conv.onePacketSize = 10
default:
return nil, icserror.ICSERRCONVNotSupportedCodec
}
var err error
conv.encoder, err = ffmpeg.NewAudioEncoderByCodecType(conv.codec.Type())
if err != nil {
fmt.Println("########111", err)
icserror.ICSERRCONVNotSupportedCodec.SetError(err)
return nil, icserror.ICSERRCONVNotSupportedCodec
}
conv.encoder.SetChannelLayout(av.CH_MONO)
conv.encoder.SetSampleRate(conv.samplingRate)
conv.encoder.SetSampleFormat(av.S16)
// fmt.Println("########222", conv.name)
}
//ffmpeg.SetLogLevel(ffmpeg.QUIET)
conv.Start()
return conv, nil
}
func (c *Converter) Start() {
c.m.Lock()
c.isStart = true
c.m.Unlock()
}
func (c *Converter) Stop() {
c.m.Lock()
c.isStart = false
c.m.Unlock()
}
func (c *Converter) IsStart() bool {
return c.isStart
}
func (c *Converter) Close() {
c.Stop()
if c.decoder != nil {
c.decoder.Close()
}
if c.encoder != nil {
c.encoder.Close()
}
l := icslog.GetIcsLog()
l.Print(icslog.LOG_LEVEL_INFO, c.ID, "Closed Converter")
}
func (c *Converter) Decode(packet []byte) ([]byte, *icserror.IcsError) {
if c == nil {
return nil, icserror.ICSERRInvalidParam
}
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "converter### Decode() packet length: %d", len(packet))
retBuf := make([]byte, PCM_8K_16BIT_10MS_SIZE*2)
packetLen := len(packet)
iter := 0
for packetLen >= c.onePacketSize {
packetLen -= c.onePacketSize
//fmt.Printf("### Decode() iter(%d) packetlen(%d)\n", iter, packetLen)
buf := packet[c.onePacketSize*iter : c.onePacketSize*(iter+1)]
//fmt.Printf("### Decode() iter(%d), buf length %d %v\n", iter, len(buf), buf)
//l.Printf(icslog.LOG_LEVEL_DEBUG2, c.ID, "### Decode() iter(%d), buf length %d %v", iter, len(buf), buf)
c.m.Lock()
if c.IsStart() {
ok, frame, errDec := c.decoder.Decode(buf)
if !ok {
icserror.ICSERRCONVDecodeFail.SetError(errDec)
//icserror.ICSERRCONVDecodeFail.Print()
c.m.Unlock()
return nil, icserror.ICSERRCONVDecodeFail
}
//fmt.Println("###frame len", iter, PCM_8K_16BIT_10MS_SIZE*iter, PCM_8K_16BIT_10MS_SIZE*(iter+1))
//fmt.Println("###frame len", len(frame.Data[0]), len(frame.Data), frame)
copy(retBuf[PCM_8K_16BIT_10MS_SIZE*iter:PCM_8K_16BIT_10MS_SIZE*(iter+1)], frame.Data[0][:PCM_8K_16BIT_10MS_SIZE])
}
c.m.Unlock()
/*
f1, err := os.OpenFile("./tx.voice.raw", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
f1.Write(frame.Data[0][:PCM_8K_16BIT_10MS_SIZE])
f1.Sync()
f1.Close()
*/
iter++
}
//fmt.Println("###retBuf len", len(retBuf), retBuf)
return retBuf, nil
}
func (c *Converter) Encode(packet []byte) ([]byte, *icserror.IcsError) {
if c == nil {
return nil, icserror.ICSERRInvalidParam
}
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "converter### Decode() packet length: %d", len(packet))
retBuf := make([]byte, PCM_8K_16BIT_10MS_SIZE)
//retBuf := make([]byte, PCM_8K_16BIT_10MS_SIZE*2)
packetLen := len(packet)
iter := 0
var onePacketSize int = c.onePacketSize
if c.codec.Type() == av.PCM_ALAW || c.codec.Type() == av.PCM_MULAW {
onePacketSize = onePacketSize
//onePacketSize = onePacketSize / 2
}
for packetLen >= onePacketSize {
packetLen -= onePacketSize
//for packetLen >= c.onePacketSize {
//packetLen -= c.onePacketSize
//fmt.Printf("### Decode() iter(%d) packetlen(%d)\n", iter, packetLen)
buf := packet[onePacketSize*iter : onePacketSize*(iter+1)]
//buf := packet[c.onePacketSize*iter : c.onePacketSize*(iter+1)]
//fmt.Printf("### Decode() iter(%d), buf length %d %v\n", iter, len(buf), buf)
//l.Printf(icslog.LOG_LEVEL_DEBUG2, c.ID, "### Decode() iter(%d), buf length %d %v", iter, len(buf), buf)
tbuf := make([][]byte, 1)
tbuf[0] = buf
frame := av.AudioFrame{
SampleFormat: av.S16,
ChannelLayout: av.CH_MONO,
SampleCount: c.onePacketSize / 2,
SampleRate: c.samplingRate,
Data: tbuf,
}
//fmt.Printf(">>>%+v\n", frame)
c.m.Lock()
if c.IsStart() {
pcmFrame, errEnc := c.encoder.Encode(frame)
//ok, frame, errDec := c.decoder.Decode(buf)
if errEnc != nil {
icserror.ICSERRCONVEncodeFail.SetError(errEnc)
//icserror.ICSERRCONVDecodeFail.Print()
c.m.Unlock()
return nil, icserror.ICSERRCONVEncodeFail
}
//fmt.Println("###frame len", iter, PCM_8K_16BIT_10MS_SIZE*iter, PCM_8K_16BIT_10MS_SIZE*(iter+1))
//fmt.Println("###frame len", len(frame.Data[0]), len(frame.Data), frame)
copy(retBuf[(PCM_8K_16BIT_10MS_SIZE/2)*iter:(PCM_8K_16BIT_10MS_SIZE/2)*(iter+1)], pcmFrame[0][:(PCM_8K_16BIT_10MS_SIZE/2)])
//copy(retBuf[PCM_8K_16BIT_10MS_SIZE*iter:PCM_8K_16BIT_10MS_SIZE*(iter+1)], pcmFrame[0][:PCM_8K_16BIT_10MS_SIZE])
//fmt.Printf("%d$$$%v", len(pcmFrame[0]), pcmFrame[0])
}
c.m.Unlock()
iter++
}
//fmt.Println("###retBuf len", len(retBuf), retBuf)
return retBuf, nil
}

@ -0,0 +1,64 @@
package icsnet
import (
"fmt"
"net"
"gitlab.com/ics_cinnamon/voicegateway/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
}

@ -0,0 +1,122 @@
package icsnet
import (
"fmt"
"net"
"strconv"
"strings"
"gitlab.com/ics_cinnamon/voicegateway/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
}

@ -0,0 +1,264 @@
package icsnet
import (
"net"
"strings"
"time"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/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() *icserror.IcsError {
var err error
if t.listener != nil {
t.conn.ICSTCPConn, err = t.listener.AcceptTCP()
if err != nil {
icserror.ICSERRNETAcceptError.SetError(err)
return icserror.ICSERRNETAcceptError
}
} else {
return icserror.ICSERRNETAcceptError
}
return 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) 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.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(*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 {
if accepterr := t.Accept(); accepterr != nil {
continue
}
go f(t, 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
}

@ -0,0 +1,267 @@
package icsnet
import (
"net"
"strconv"
"time"
"gitlab.com/ics_cinnamon/voicegateway/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)))
}

@ -0,0 +1,11 @@
package icspacketer
import (
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
)
//SIP/RTP parser interface
type Packeter interface {
GetPacketData(addr []*icsnet.IcsNetAddr, packet []byte) *icserror.IcsError
}

@ -0,0 +1,195 @@
/*
RFC 3550. RTP: A Transport Protocol for Real-Time Applications
*/
package icspacketparser
import (
"encoding/binary"
"fmt"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
)
type RTP struct {
Version int
Mark bool
PayloadType PayloadType
Seq uint16
Timestamp uint32
SSID uint32
PayloadLen int
Payload []byte
SrcAddr *icsnet.IcsNetAddr
DstAddr *icsnet.IcsNetAddr
}
type RTPHeader struct {
v byte //2bits
m byte //1
pt byte //7
seq []byte //16
ts []byte //4
ssrc []byte //4
}
type PayloadType int
const RTPHeaderLen = 12
//RTP payload type
const (
PCMU PayloadType = 0
PCMA PayloadType = 8
G729 PayloadType = 18
DTMF101 PayloadType = 101
)
type RTPPayloadType struct {
Name string
PType PayloadType
SamplingRate int
PTime int
PSize int
}
func NewRTPPayloadType(t PayloadType) *RTPPayloadType {
var pt RTPPayloadType
switch t {
case PCMU:
pt = RTPPayloadType{
Name: "PCMU",
PType: t,
SamplingRate: 8000,
PTime: 20,
PSize: 160,
}
case PCMA:
pt = RTPPayloadType{
Name: "PCMA",
PType: t,
SamplingRate: 8000,
PTime: 20,
PSize: 160,
}
case G729:
pt = RTPPayloadType{
Name: "G729",
PType: t,
SamplingRate: 8000,
PTime: 20,
PSize: 160,
}
case DTMF101:
pt = RTPPayloadType{
Name: "DTMF101",
PType: t,
SamplingRate: 8000,
PTime: 20,
PSize: 160,
}
}
return &pt
}
var RTPPayloadInfo map[PayloadType]*RTPPayloadType
func init() {
RTPPayloadInfo = make(map[PayloadType]*RTPPayloadType, 100)
RTPPayloadInfo[PCMU] = NewRTPPayloadType(PCMU)
RTPPayloadInfo[PCMA] = NewRTPPayloadType(PCMA)
RTPPayloadInfo[G729] = NewRTPPayloadType(G729)
RTPPayloadInfo[DTMF101] = NewRTPPayloadType(DTMF101)
}
func NewRTP() RTP {
rtp := RTP{}
return rtp
}
func (r *RTP) RTPParser(data []byte) *icserror.IcsError {
datalen := len(data)
if datalen <= RTPHeaderLen {
return icserror.ICSERRRTPNo
}
//fmt.Println(data)
r.PayloadLen = datalen - RTPHeaderLen
//fmt.Println("Payload Len:", r.PayloadLen)
header := RTPHeader{}
//RTP version 2bit
header.v = data[0] >> 6
r.Version = int(header.v)
if r.Version != 2 {
return icserror.ICSERRRTPNo
}
//fmt.Println("Version", r.Version)
//mark 1bit
header.m = data[1] >> 7
//fmt.Println("Mark", header.m)
r.Mark = header.m == 1
//payload type 7bit
ptint := data[1]
ptint = ptint << 1
header.pt = ptint >> 1
r.PayloadType = PayloadType(header.pt)
//fmt.Println("PayloadType:", r.PayloadType)
if r.PayloadType == 18 { //g729
if datalen != 32 {
return icserror.ICSERRRTPNo
}
}
header.seq = make([]byte, 2)
copy(header.seq, data[2:4])
r.Seq = binary.BigEndian.Uint16(header.seq[0:])
//fmt.Println("SEQ:", r.Seq)
header.ts = make([]byte, 4)
copy(header.ts, data[4:8])
r.Timestamp = binary.BigEndian.Uint32(header.ts[0:])
//fmt.Println("Timestamp:", r.Timestamp)
header.ssrc = make([]byte, 4)
copy(header.ssrc, data[8:12])
r.SSID = binary.BigEndian.Uint32(header.ssrc[0:])
//fmt.Println("SSID:", r.SSID)
r.Payload = make([]byte, r.PayloadLen)
copy(r.Payload, data[12:])
//fmt.Println("Payload data:", r.Payload)
return nil
}
//implm interface Packeter
func (r *RTP) GetPacketData(addr []*icsnet.IcsNetAddr, packet []byte) *icserror.IcsError {
r.SrcAddr = addr[0]
r.DstAddr = addr[1]
//fmt.Println("RTP GetPacketData()", r.SrcAddr, r.DstAddr)
if err := r.RTPParser(packet); err != nil {
//err.Print()
return err
}
return nil
}
func (r RTP) GetPayloadType() PayloadType {
return r.PayloadType
}
func (r RTP) GetPayloadLen() int {
return r.PayloadLen
}
func (r RTP) String() string {
return fmt.Sprintf("ssrc: %d, seq: %d, ts: %d, pt: %d, payload len: %d", r.SSID, r.Seq, r.Timestamp, r.PayloadType, r.PayloadLen)
}

@ -0,0 +1,38 @@
package icspacketparser
import (
"strconv"
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
)
type SDPMedia struct {
MediaDescription string // m
Attributes []string // a
Payload []string // codec
}
func (sdm *SDPMedia) setSdpMediaStruct(name string, value string) (icserr *icserror.IcsError) {
switch strings.ToUpper(name) {
case "M":
//fmt.Println(name, value)
sdm.MediaDescription = value
spaceSplitValue := strings.Split(value, " ")
for i, fieldValue := range spaceSplitValue {
intValue, err := strconv.Atoi(strings.TrimSpace(fieldValue))
if i >= 3 && err == nil {
sdm.Payload = append(sdm.Payload, strconv.Itoa(intValue))
}
}
// fmt.Println("sdm.Payload >>>>>>>>>>>", sdm.Payload)
return nil
case "A":
sdm.Attributes = append(sdm.Attributes, value)
return nil
default:
//fmt.Println("SDP Media~~~~~~~~~~~~~~~~~whoAU~~~~~~~~~~~~~~~~~")
}
return nil
}

@ -0,0 +1,44 @@
package icspacketparser
import (
"strconv"
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
)
type SDP struct {
Version uint8 // v
Owner string // o
Session string // s
Connection string // c
Timing string // t
Media *[]SDPMedia // m a
}
func (sd *SDP) setSdpStruct(name string, value string) (icserr *icserror.IcsError) {
switch strings.ToUpper(name) {
case "V":
numValue, err := strconv.ParseUint(value, 10, 64)
if err != nil {
return icserror.ICSERRSDPParser
}
sd.Version = uint8(numValue)
return nil
case "O":
sd.Owner = value
return nil
case "S":
sd.Session = value
return nil
case "C":
sd.Connection = value
return nil
case "T":
sd.Timing = value
return nil
default:
//fmt.Println("SDP~~~~~~~~~~~~~~~~~whoAU~~~~~~~~~~~~~~~~~")
}
return nil
}

@ -0,0 +1,382 @@
package icspacketparser
import (
"strconv"
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
)
type IcsSipMethod int
const (
ICS_SIP_METHOD_REGISTER IcsSipMethod = iota
ICS_SIP_METHOD_INVITE
ICS_SIP_METHOD_PUBLISH
ICS_SIP_METHOD_OPTIONS
ICS_SIP_METHOD_INFO
ICS_SIP_METHOD_UPDATE
ICS_SIP_METHOD_REFER
ICS_SIP_METHOD_SUBSCRIBE
ICS_SIP_METHOD_MESSAGE
ICS_SIP_METHOD_NOTIFY
ICS_SIP_METHOD_PRACK
ICS_SIP_METHOD_ACK
ICS_SIP_METHOD_BYE
ICS_SIP_METHOD_CANCEL
ICS_SIP_METHOD_SIP20 //response
ICS_SIP_METHOD_NOT_FOUND
)
func (arr IcsSipMethod) String() string {
var strSipMethod = []string{
"ICS_SIP_METHOD_REGISTER",
"ICS_SIP_METHOD_INVITE",
"ICS_SIP_METHOD_PUBLISH",
"ICS_SIP_METHOD_OPTIONS",
"ICS_SIP_METHOD_INFO",
"ICS_SIP_METHOD_UPDATE",
"ICS_SIP_METHOD_REFER",
"ICS_SIP_METHOD_SUBSCRIBE",
"ICS_SIP_METHOD_MESSAGE",
"ICS_SIP_METHOD_NOTIFY",
"ICS_SIP_METHOD_PRACK",
"ICS_SIP_METHOD_ACK",
"ICS_SIP_METHOD_BYE",
"ICS_SIP_METHOD_CANCEL",
"ICS_SIP_METHOD_SIP20",
"ICS_SIP_METHOD_NOT_FOUND",
}
return strSipMethod[int(arr)%len(strSipMethod)]
}
type SIP struct {
Headers map[string][]string
Method IcsSipMethod
Version string
Source string
Via []string
MaxForwards int64
Contact string
To string
// ToTag string
From string
// FromTag string
RecordRoute string
RequestURI string
CallID string
UserAgent string
Allow string
Supported string
Cseq string
ContentLength int64
ContentType string
ResType string
XAICall string
// direction bool
Content *SDP
SrcAddr *icsnet.IcsNetAddr
DstAddr *icsnet.IcsNetAddr
}
func NewSIP() (sip SIP) {
return sip
}
func NewSDP() (sdp SDP) {
return sdp
}
func NewSDPMedia() (sdpMedia SDPMedia) {
return sdpMedia
}
var sdpMediaType = []string{"m", "a"}
func findSdpMedia(mediaType string) bool {
for _, value := range sdpMediaType {
if value == mediaType {
return true
}
}
return false
}
func (s *SIP) SipParser(byteArr []byte) (icserr *icserror.IcsError) {
strSipLine := strings.Split(string(byteArr), "\r\n")
isParserSIP := true
sdp := NewSDP()
sdpMedia := SDPMedia{}
sdpMedias := []SDPMedia{}
for line := range strSipLine {
//fmt.Println("strSipLine[line]", len(strings.TrimSpace(strSipLine[line])), isParserSIP, strings.TrimSpace(strSipLine[line]))
if line == 0 {
s.parseFirstLineHeader(strings.TrimSpace(strSipLine[line]))
} else {
if isParserSIP && len(strings.TrimSpace(strSipLine[line])) == 0 {
isParserSIP = false
} else if !isParserSIP && len(strings.TrimSpace(strSipLine[line])) == 0 {
break
} else if !isParserSIP { //parse SDP
if len(strings.TrimSpace(strSipLine[line])) > 0 {
if len(strings.TrimSpace(strSipLine[line])) == 0 {
//fmt.Println("RRRR", line)
return nil
}
splits := strings.SplitN(string(strings.TrimSpace(strSipLine[line])), "=", 2)
if len(splits) < 2 {
//fmt.Printf("RRRR22 strSipLine[line] : [%s]\n", strSipLine[line])
//fmt.Printf("RRRR22 strSipLine len: %d, line len: %d, byteArr: {%s}, SipLine:##### {%v}\n",
//len(strSipLine), line, string(byteArr), strSipLine)
break
//return nil
}
name := strings.TrimSpace(splits[0])
value := strings.TrimSpace(splits[1])
//fmt.Println("@@@@", name, value)
if findSdpMedia(name) {
sdpMedia.setSdpMediaStruct(name, value)
} else {
sdp.setSdpStruct(name, value)
}
}
} else {
s.parseSip(strings.TrimSpace(strSipLine[line]))
}
}
}
sdpMedias = append(sdpMedias, sdpMedia)
if isExistSdpMedia(sdpMedias) {
//fmt.Println("$$$$", sdpMedias)
//fmt.Printf("MediaDescription: %s", sdpMedias[0].MediaDescription)
sdp.Media = &sdpMedias
}
// fmt.Println("sdp.Version", sdp.Version)
// fmt.Println("sdp.Owner", sdp.Owner)
// fmt.Println("sdp.Session", sdp.Session)
// fmt.Println("sdp.Connection", sdp.Connection)
if isExistSdp(sdp) {
s.Content = &sdp
}
return nil
}
func isExistSdpMedia(sdpMedias []SDPMedia) bool {
for _, value := range sdpMedias {
if len(value.MediaDescription) == 0 {
return false
}
// TODO Media만 존재하고, attributes 가 없는 경우 처리 방법
// for _, val := range value.Attributes {
// fmt.Println(val)
// }
}
return true
}
func isExistSdp(sdp SDP) bool {
if sdp.Version == 0 && sdp.Owner == "" && sdp.Session == "" && sdp.Connection == "" {
return false
}
return true
}
func (s *SIP) parseFirstLineHeader(strSipLine string) (icserr *icserror.IcsError) {
// fmt.Println(">>>>>>>>>>>parseFirstLineHeader", strSipLine)
splits := strings.SplitN(strSipLine, " ", 3)
if len(splits) < 3 {
return icserror.ICSERRSIPHeader
}
icsSipMethod, err := GetSipMethod(splits[0], splits[1])
if icsSipMethod == ICS_SIP_METHOD_SIP20 {
s.ResType = splits[1]
}
if err != nil {
return icserror.ICSERRSIPHeader
}
s.Method = icsSipMethod
s.Version = splits[2]
s.Source = splits[1]
return nil
}
func GetSipMethod(strMethod, strSource string) (icsSipMethod IcsSipMethod, icserr *icserror.IcsError) {
for method := IcsSipMethod(0); method < ICS_SIP_METHOD_NOT_FOUND; method++ {
switch strings.ToUpper(strMethod) {
case "REGISTER":
return ICS_SIP_METHOD_REGISTER, nil
case "INVITE":
return ICS_SIP_METHOD_INVITE, nil
case "SIP/2.0":
return ICS_SIP_METHOD_SIP20, nil
case "PRACK":
return ICS_SIP_METHOD_PRACK, nil
case "ACK":
return ICS_SIP_METHOD_ACK, nil
case "BYE":
return ICS_SIP_METHOD_BYE, nil
case "REFER":
return ICS_SIP_METHOD_REFER, nil
case "NOTIFY":
return ICS_SIP_METHOD_NOTIFY, nil
case "CANCEL":
return ICS_SIP_METHOD_CANCEL, nil
case "INFO":
return ICS_SIP_METHOD_INFO, nil
case "OPTIONS":
return ICS_SIP_METHOD_OPTIONS, nil
case "SUBSCRIBE":
return ICS_SIP_METHOD_SUBSCRIBE, nil
case "PUBLISH":
return ICS_SIP_METHOD_PUBLISH, nil
case "UPDATE":
return ICS_SIP_METHOD_UPDATE, nil
}
}
return ICS_SIP_METHOD_NOT_FOUND, nil
}
func (s *SIP) parseSip(data string) (icserr *icserror.IcsError) {
if len(data) == 0 {
return nil
}
splits := strings.SplitN(string(data), ":", 2)
if len(splits) < 2 {
return nil
}
name := strings.TrimSpace(splits[0])
value := strings.TrimSpace(splits[1])
s.setSipStruct(name, value)
return nil
}
func (s *SIP) setSipStruct(name string, value string) (icserr *icserror.IcsError) {
switch strings.ToUpper(name) {
case "VIA":
s.Via = append(s.Via, value)
return nil
case "MAX-FORWARDS":
numValue, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return icserror.ICSERRSIPHeader
}
s.MaxForwards = numValue
return nil
case "FROM":
s.From = value
// splits := strings.SplitN(string(value), "tag=", 2)
// if len(splits) < 2 {
// s.FromTag = ""
// } else {
// s.FromTag = strings.TrimSpace(splits[1])
// }
return nil
case "TO":
s.To = value
return nil
case "CALL-ID":
s.CallID = value
return nil
case "CSEQ":
// splits := strings.SplitN(string(value), " ", 2)
// numValue, err := strconv.ParseInt(strings.TrimSpace(splits[0]), 10, 64)
// if err != nil {
// return icserror.ICSERRSIPHeader
// }
// s.Cseq = numValue
s.Cseq = strings.ToUpper(value)
return nil
case "CONTACT":
s.Contact = value
return nil
case "SUPPORTED":
s.Supported = value
return nil
case "ALLOW":
s.Allow = value
return nil
case "USER-AGENT":
s.UserAgent = value
return nil
case "CONTENT-TYPE":
s.ContentType = value
return nil
case "CONTENT-LENGTH":
numValue, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return icserror.ICSERRSIPHeader
}
s.ContentLength = numValue
return nil
case "X-AICALL":
s.XAICall = value
default:
values := strings.Split(value, ";")
// 헤더 값에 값을 없을 경우 초기화.. map이라서??
if len(s.Headers) == 0 {
s.Headers = map[string][]string{}
}
for _, fieldValue := range values {
s.Headers[name] = append(s.Headers[name], strings.TrimSpace(fieldValue))
}
//fmt.Println("SIP~~~~~~~~~~~~~~~~~whoAU~~~~~~~~~~~~~~~~~" + value)
}
return nil
}
//implm interface Packeter
func (s *SIP) GetPacketData(addr []*icsnet.IcsNetAddr, packet []byte) *icserror.IcsError {
s.SrcAddr = addr[0]
s.DstAddr = addr[1]
return s.SipParser(packet)
//fmt.Println("SIP GetPacketData()", s.SrcAddr, s.DstAddr)
}
func (s *SIP) GetCallID() string {
return s.CallID
}
func (s *SIP) GetURI() string {
if s.Method != ICS_SIP_METHOD_SIP20 {
uris := strings.SplitN(s.Source, ";", 2)
if len(uris[0]) > 0 {
agenturis := strings.SplitN(uris[0], ":", 3)
//fmt.Println(">>>", uris, s.Method)
return agenturis[1]
}
}
return ""
}

@ -0,0 +1,114 @@
package icspacketparser
import (
"fmt"
"testing"
)
func TestGetModName(t *testing.T) {
// invite
// sipByteArray := []byte{73, 78, 86, 73, 84, 69, 32, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 32, 83, 73, 80, 47, 50, 46, 48, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 97, 99, 55, 50, 55, 53, 53, 53, 56, 54, 50, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 54, 57, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 49, 62, 59, 116, 97, 103, 61, 49, 99, 49, 50, 52, 57, 54, 53, 56, 56, 57, 50, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 59, 117, 115, 101, 114, 61, 112, 104, 111, 110, 101, 62, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 51, 48, 57, 54, 54, 56, 56, 48, 48, 50, 56, 50, 50, 48, 49, 56, 49, 53, 52, 54, 52, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 49, 48, 48, 114, 101, 108, 44, 116, 105, 109, 101, 114, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 44, 115, 100, 112, 45, 97, 110, 97, 116, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 115, 100, 112, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 51, 48, 53, 10, 10, 118, 61, 48, 10, 111, 61, 65, 117, 100, 105, 111, 99, 111, 100, 101, 115, 71, 87, 32, 49, 52, 56, 51, 48, 51, 56, 48, 56, 32, 49, 55, 50, 48, 56, 52, 54, 50, 53, 57, 32, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 115, 61, 80, 104, 111, 110, 101, 45, 67, 97, 108, 108, 10, 99, 61, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 116, 61, 48, 32, 48, 10, 109, 61, 97, 117, 100, 105, 111, 32, 55, 56, 53, 48, 32, 82, 84, 80, 47, 65, 86, 80, 32, 56, 32, 48, 32, 49, 56, 32, 49, 48, 49, 10, 97, 61, 112, 116, 105, 109, 101, 58, 50, 48, 10, 97, 61, 115, 101, 110, 100, 114, 101, 99, 118, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 56, 32, 80, 67, 77, 65, 47, 56, 48, 48, 48, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 48, 32, 80, 67, 77, 85, 47, 56, 48, 48, 48, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 56, 32, 71, 55, 50, 57, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 56, 32, 97, 110, 110, 101, 120, 98, 61, 110, 111, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 48, 49, 32, 116, 101, 108, 101, 112, 104, 111, 110, 101, 45, 101, 118, 101, 110, 116, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 48, 49, 32, 48, 45, 49, 53, 10}
// 180 ringing
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 49, 56, 48, 32, 82, 105, 110, 103, 105, 110, 103, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 49, 62, 59, 116, 97, 103, 61, 49, 99, 49, 50, 52, 57, 54, 53, 56, 56, 57, 50, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 59, 117, 115, 101, 114, 61, 112, 104, 111, 110, 101, 62, 59, 116, 97, 103, 61, 55, 53, 54, 54, 101, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 98, 101, 48, 97, 45, 49, 55, 54, 57, 54, 53, 102, 51, 45, 50, 98, 101, 48, 97, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 51, 48, 57, 54, 54, 56, 56, 48, 48, 50, 56, 50, 50, 48, 49, 56, 49, 53, 52, 54, 52, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 97, 99, 55, 50, 55, 53, 53, 53, 56, 54, 50, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 62, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
// 200 ok
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 50, 48, 48, 32, 79, 75, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 49, 62, 59, 116, 97, 103, 61, 49, 99, 49, 50, 52, 57, 54, 53, 56, 56, 57, 50, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 59, 117, 115, 101, 114, 61, 112, 104, 111, 110, 101, 62, 59, 116, 97, 103, 61, 55, 53, 54, 54, 101, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 98, 101, 48, 97, 45, 49, 55, 54, 57, 54, 53, 102, 51, 45, 50, 98, 101, 48, 97, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 51, 48, 57, 54, 54, 56, 56, 48, 48, 50, 56, 50, 50, 48, 49, 56, 49, 53, 52, 54, 52, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 97, 99, 55, 50, 55, 53, 53, 53, 56, 54, 50, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 62, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 115, 100, 112, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 50, 49, 55, 10, 10, 118, 61, 48, 10, 111, 61, 57, 48, 48, 49, 32, 49, 54, 49, 51, 54, 51, 51, 54, 56, 56, 32, 49, 54, 49, 51, 54, 51, 51, 54, 56, 56, 32, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 10, 115, 61, 45, 10, 99, 61, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 10, 116, 61, 48, 32, 48, 10, 109, 61, 97, 117, 100, 105, 111, 32, 52, 48, 50, 50, 32, 82, 84, 80, 47, 65, 86, 80, 32, 49, 56, 32, 49, 48, 49, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 56, 32, 71, 55, 50, 57, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 56, 32, 97, 110, 110, 101, 120, 98, 61, 110, 111, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 48, 49, 32, 116, 101, 108, 101, 112, 104, 111, 110, 101, 45, 101, 118, 101, 110, 116, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 48, 49, 32, 48, 45, 49, 53, 10}
// ack
// sipByteArray := []byte{65, 67, 75, 32, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 32, 83, 73, 80, 47, 50, 46, 48, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 97, 99, 49, 57, 49, 50, 48, 53, 50, 55, 53, 48, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 54, 57, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 49, 62, 59, 116, 97, 103, 61, 49, 99, 49, 50, 52, 57, 54, 53, 56, 56, 57, 50, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 59, 117, 115, 101, 114, 61, 112, 104, 111, 110, 101, 62, 59, 116, 97, 103, 61, 55, 53, 54, 54, 101, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 98, 101, 48, 97, 45, 49, 55, 54, 57, 54, 53, 102, 51, 45, 50, 98, 101, 48, 97, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 51, 48, 57, 54, 54, 56, 56, 48, 48, 50, 56, 50, 50, 48, 49, 56, 49, 53, 52, 54, 52, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 67, 83, 101, 113, 58, 32, 49, 32, 65, 67, 75, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 116, 105, 109, 101, 114, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
// bye
// sipByteArray := []byte{66, 89, 69, 32, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 32, 83, 73, 80, 47, 50, 46, 48, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 59, 117, 115, 101, 114, 61, 112, 104, 111, 110, 101, 62, 59, 116, 97, 103, 61, 55, 53, 54, 54, 101, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 98, 101, 48, 97, 45, 49, 55, 54, 57, 54, 53, 102, 51, 45, 50, 98, 101, 48, 97, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 49, 62, 59, 116, 97, 103, 61, 49, 99, 49, 50, 52, 57, 54, 53, 56, 56, 57, 50, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 51, 48, 57, 54, 54, 56, 56, 48, 48, 50, 56, 50, 50, 48, 49, 56, 49, 53, 52, 54, 52, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 67, 83, 101, 113, 58, 32, 49, 32, 66, 89, 69, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 112, 111, 114, 116, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 50, 98, 101, 49, 54, 45, 97, 98, 54, 56, 55, 55, 50, 45, 55, 101, 55, 101, 53, 102, 52, 57, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 55, 48, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
// 200ok
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 50, 48, 48, 32, 79, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 50, 98, 101, 49, 54, 45, 97, 98, 54, 56, 55, 55, 50, 45, 55, 101, 55, 101, 53, 102, 52, 57, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 59, 117, 115, 101, 114, 61, 112, 104, 111, 110, 101, 62, 59, 116, 97, 103, 61, 55, 53, 54, 54, 101, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 98, 101, 48, 97, 45, 49, 55, 54, 57, 54, 53, 102, 51, 45, 50, 98, 101, 48, 97, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 49, 62, 59, 116, 97, 103, 61, 49, 99, 49, 50, 52, 57, 54, 53, 56, 56, 57, 50, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 51, 48, 57, 54, 54, 56, 56, 48, 48, 50, 56, 50, 50, 48, 49, 56, 49, 53, 52, 54, 52, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 67, 83, 101, 113, 58, 32, 49, 32, 66, 89, 69, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 50, 53, 54, 55, 48, 48, 56, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 116, 105, 109, 101, 114, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
//0.REGISTER
// sipByteArray := []byte{82, 69, 71, 73, 83, 84, 69, 82, 32, 115, 105, 112, 58, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 32, 83, 73, 80, 47, 50, 46, 48, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 62, 59, 116, 97, 103, 61, 55, 52, 100, 99, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 45, 50, 51, 57, 51, 102, 50, 100, 52, 45, 50, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 62, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 57, 97, 53, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 45, 53, 56, 100, 98, 49, 100, 100, 54, 45, 50, 10, 67, 83, 101, 113, 58, 32, 49, 32, 82, 69, 71, 73, 83, 84, 69, 82, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 112, 111, 114, 116, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 50, 45, 57, 51, 97, 45, 55, 101, 100, 54, 51, 98, 57, 54, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 55, 48, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 69, 120, 112, 105, 114, 101, 115, 58, 32, 51, 54, 48, 48, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 62, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
//1.200OK
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 50, 48, 48, 32, 79, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 50, 45, 57, 51, 97, 45, 55, 101, 100, 54, 51, 98, 57, 54, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 62, 59, 116, 97, 103, 61, 55, 52, 100, 99, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 45, 50, 51, 57, 51, 102, 50, 100, 52, 45, 50, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 62, 59, 116, 97, 103, 61, 49, 99, 53, 51, 52, 54, 48, 52, 49, 56, 48, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 57, 97, 53, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 50, 45, 53, 56, 100, 98, 49, 100, 100, 54, 45, 50, 10, 67, 83, 101, 113, 58, 32, 49, 32, 82, 69, 71, 73, 83, 84, 69, 82, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 62, 59, 101, 120, 112, 105, 114, 101, 115, 61, 51, 54, 48, 48, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 69, 120, 112, 105, 114, 101, 115, 58, 32, 51, 54, 48, 48, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
//00.INVITE.txt
// sipByteArray := []byte{73, 78, 86, 73, 84, 69, 32, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 32, 83, 73, 80, 47, 50, 46, 48, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 112, 111, 114, 116, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 51, 45, 50, 56, 102, 52, 97, 99, 97, 97, 45, 51, 101, 100, 49, 98, 98, 49, 49, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 55, 48, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 62, 10, 83, 101, 115, 115, 105, 111, 110, 45, 69, 120, 112, 105, 114, 101, 115, 58, 32, 49, 56, 48, 48, 10, 77, 105, 110, 45, 83, 69, 58, 32, 57, 48, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 115, 100, 112, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 50, 50, 57, 10, 10, 118, 61, 48, 10, 111, 61, 57, 48, 48, 49, 32, 49, 54, 49, 56, 57, 48, 50, 55, 55, 53, 32, 49, 54, 49, 56, 57, 48, 50, 55, 55, 53, 32, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 10, 115, 61, 45, 10, 99, 61, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 10, 116, 61, 48, 32, 48, 10, 109, 61, 97, 117, 100, 105, 111, 32, 52, 48, 57, 54, 32, 82, 84, 80, 47, 65, 86, 80, 32, 49, 56, 32, 49, 48, 49, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 56, 32, 71, 55, 50, 57, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 56, 32, 97, 110, 110, 101, 120, 98, 61, 110, 111, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 48, 49, 32, 116, 101, 108, 101, 112, 104, 111, 110, 101, 45, 101, 118, 101, 110, 116, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 48, 49, 32, 48, 45, 49, 53, 10, 97, 61, 115, 101, 110, 100, 114, 101, 99, 118, 10}
//01.100Trying.txt
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 49, 48, 48, 32, 84, 114, 121, 105, 110, 103, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 51, 45, 50, 56, 102, 52, 97, 99, 97, 97, 45, 51, 101, 100, 49, 98, 98, 49, 49, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10}
//02.183SessionProgress.txt
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 49, 56, 51, 32, 83, 101, 115, 115, 105, 111, 110, 32, 80, 114, 111, 103, 114, 101, 115, 115, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 51, 45, 50, 56, 102, 52, 97, 99, 97, 97, 45, 51, 101, 100, 49, 98, 98, 49, 49, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 116, 105, 109, 101, 114, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 44, 115, 100, 112, 45, 97, 110, 97, 116, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 82, 101, 113, 117, 105, 114, 101, 58, 32, 49, 48, 48, 114, 101, 108, 10, 82, 83, 101, 113, 58, 32, 49, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 115, 100, 112, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 50, 53, 56, 10, 10, 118, 61, 48, 10, 111, 61, 65, 117, 100, 105, 111, 99, 111, 100, 101, 115, 71, 87, 32, 49, 51, 48, 54, 50, 50, 54, 51, 54, 55, 32, 49, 55, 56, 48, 48, 51, 54, 50, 48, 53, 32, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 115, 61, 80, 104, 111, 110, 101, 45, 67, 97, 108, 108, 10, 99, 61, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 116, 61, 48, 32, 48, 10, 109, 61, 97, 117, 100, 105, 111, 32, 55, 50, 56, 48, 32, 82, 84, 80, 47, 65, 86, 80, 32, 49, 56, 32, 49, 48, 49, 10, 97, 61, 115, 101, 110, 100, 114, 101, 99, 118, 10, 97, 61, 112, 116, 105, 109, 101, 58, 50, 48, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 56, 32, 71, 55, 50, 57, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 56, 32, 97, 110, 110, 101, 120, 98, 61, 110, 111, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 48, 49, 32, 116, 101, 108, 101, 112, 104, 111, 110, 101, 45, 101, 118, 101, 110, 116, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 48, 49, 32, 48, 45, 49, 53, 10}
//03.PRACK.txt
// sipByteArray := []byte{80, 82, 65, 67, 75, 32, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 32, 83, 73, 80, 47, 50, 46, 48, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 50, 32, 80, 82, 65, 67, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 112, 111, 114, 116, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 51, 45, 50, 56, 102, 52, 97, 100, 54, 51, 45, 52, 97, 53, 54, 97, 56, 98, 102, 10, 82, 65, 99, 107, 58, 32, 49, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 55, 48, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10}
//04.200OK.txt
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 50, 48, 48, 32, 79, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 51, 45, 50, 56, 102, 52, 97, 100, 54, 51, 45, 52, 97, 53, 54, 97, 56, 98, 102, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 50, 32, 80, 82, 65, 67, 75, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 116, 105, 109, 101, 114, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10}
//05.180Ringing.txt
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 49, 56, 48, 32, 82, 105, 110, 103, 105, 110, 103, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 51, 45, 50, 56, 102, 52, 97, 99, 97, 97, 45, 51, 101, 100, 49, 98, 98, 49, 49, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 116, 105, 109, 101, 114, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 44, 115, 100, 112, 45, 97, 110, 97, 116, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 82, 101, 113, 117, 105, 114, 101, 58, 32, 49, 48, 48, 114, 101, 108, 10, 82, 83, 101, 113, 58, 32, 50, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 115, 100, 112, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 50, 53, 56, 10, 10, 118, 61, 48, 10, 111, 61, 65, 117, 100, 105, 111, 99, 111, 100, 101, 115, 71, 87, 32, 49, 51, 48, 54, 50, 50, 54, 51, 54, 55, 32, 49, 55, 56, 48, 48, 51, 54, 50, 48, 53, 32, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 115, 61, 80, 104, 111, 110, 101, 45, 67, 97, 108, 108, 10, 99, 61, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 116, 61, 48, 32, 48, 10, 109, 61, 97, 117, 100, 105, 111, 32, 55, 50, 56, 48, 32, 82, 84, 80, 47, 65, 86, 80, 32, 49, 56, 32, 49, 48, 49, 10, 97, 61, 115, 101, 110, 100, 114, 101, 99, 118, 10, 97, 61, 112, 116, 105, 109, 101, 58, 50, 48, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 56, 32, 71, 55, 50, 57, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 56, 32, 97, 110, 110, 101, 120, 98, 61, 110, 111, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 48, 49, 32, 116, 101, 108, 101, 112, 104, 111, 110, 101, 45, 101, 118, 101, 110, 116, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 48, 49, 32, 48, 45, 49, 53, 10}
//06.PRACK.txt
// sipByteArray := []byte{80, 82, 65, 67, 75, 32, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 32, 83, 73, 80, 47, 50, 46, 48, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 51, 32, 80, 82, 65, 67, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 112, 111, 114, 116, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 53, 45, 50, 56, 102, 52, 98, 51, 98, 98, 45, 53, 54, 50, 55, 99, 51, 52, 100, 10, 82, 65, 99, 107, 58, 32, 50, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 55, 48, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10}
//07.200OK.txt
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 50, 48, 48, 32, 79, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 53, 45, 50, 56, 102, 52, 98, 51, 98, 98, 45, 53, 54, 50, 55, 99, 51, 52, 100, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 51, 32, 80, 82, 65, 67, 75, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 116, 105, 109, 101, 114, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10}
//08.200OK.txt
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 50, 48, 48, 32, 79, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 51, 45, 50, 56, 102, 52, 97, 99, 97, 97, 45, 51, 101, 100, 49, 98, 98, 49, 49, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 44, 115, 100, 112, 45, 97, 110, 97, 116, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 82, 101, 113, 117, 105, 114, 101, 58, 32, 116, 105, 109, 101, 114, 10, 83, 101, 115, 115, 105, 111, 110, 45, 69, 120, 112, 105, 114, 101, 115, 58, 32, 49, 56, 48, 48, 59, 114, 101, 102, 114, 101, 115, 104, 101, 114, 61, 117, 97, 115, 10, 77, 105, 110, 45, 83, 69, 58, 32, 57, 48, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 115, 100, 112, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 50, 53, 56, 10, 10, 118, 61, 48, 10, 111, 61, 65, 117, 100, 105, 111, 99, 111, 100, 101, 115, 71, 87, 32, 49, 51, 48, 54, 50, 50, 54, 51, 54, 55, 32, 49, 55, 56, 48, 48, 51, 54, 50, 48, 53, 32, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 115, 61, 80, 104, 111, 110, 101, 45, 67, 97, 108, 108, 10, 99, 61, 73, 78, 32, 73, 80, 52, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 10, 116, 61, 48, 32, 48, 10, 109, 61, 97, 117, 100, 105, 111, 32, 55, 50, 56, 48, 32, 82, 84, 80, 47, 65, 86, 80, 32, 49, 56, 32, 49, 48, 49, 10, 97, 61, 115, 101, 110, 100, 114, 101, 99, 118, 10, 97, 61, 112, 116, 105, 109, 101, 58, 50, 48, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 56, 32, 71, 55, 50, 57, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 56, 32, 97, 110, 110, 101, 120, 98, 61, 110, 111, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 49, 48, 49, 32, 116, 101, 108, 101, 112, 104, 111, 110, 101, 45, 101, 118, 101, 110, 116, 47, 56, 48, 48, 48, 10, 97, 61, 102, 109, 116, 112, 58, 49, 48, 49, 32, 48, 45, 49, 53, 10}
//09.ACK.txt
// sipByteArray := []byte{65, 67, 75, 32, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 32, 83, 73, 80, 47, 50, 46, 48, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 49, 32, 65, 67, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 112, 111, 114, 116, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 97, 55, 99, 49, 97, 45, 50, 56, 102, 52, 99, 56, 49, 98, 45, 55, 101, 48, 100, 100, 49, 98, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 55, 48, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 62, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10}
//10.BYE.txt
// sipByteArray := []byte{66, 89, 69, 32, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 32, 83, 73, 80, 47, 50, 46, 48, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 97, 99, 49, 50, 52, 56, 49, 52, 56, 52, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 54, 57, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 84, 111, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 49, 32, 66, 89, 69, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 101, 109, 44, 116, 105, 109, 101, 114, 44, 114, 101, 112, 108, 97, 99, 101, 115, 44, 112, 97, 116, 104, 44, 114, 101, 115, 111, 117, 114, 99, 101, 45, 112, 114, 105, 111, 114, 105, 116, 121, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 79, 80, 84, 73, 79, 78, 83, 44, 73, 78, 86, 73, 84, 69, 44, 65, 67, 75, 44, 67, 65, 78, 67, 69, 76, 44, 66, 89, 69, 44, 78, 79, 84, 73, 70, 89, 44, 80, 82, 65, 67, 75, 44, 82, 69, 70, 69, 82, 44, 73, 78, 70, 79, 44, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 85, 80, 68, 65, 84, 69, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 82, 101, 97, 115, 111, 110, 58, 32, 81, 46, 56, 53, 48, 32, 59, 99, 97, 117, 115, 101, 61, 49, 54, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10}
//11.200OK.txt
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 50, 48, 48, 32, 79, 75, 10, 70, 114, 111, 109, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 50, 49, 51, 48, 52, 57, 49, 48, 51, 51, 10, 84, 111, 58, 32, 34, 57, 48, 48, 49, 34, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 53, 54, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 52, 50, 53, 57, 51, 49, 97, 56, 45, 97, 55, 99, 49, 51, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 54, 49, 49, 56, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 97, 55, 99, 49, 51, 45, 55, 102, 54, 98, 56, 48, 54, 50, 45, 97, 55, 99, 49, 51, 10, 67, 83, 101, 113, 58, 32, 49, 32, 66, 89, 69, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 97, 99, 49, 50, 52, 56, 49, 52, 56, 52, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
//20.CANCEL.txt
// sipByteArray := []byte{67, 65, 78, 67, 69, 76, 32, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 32, 83, 73, 80, 47, 50, 46, 48, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 49, 57, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 101, 57, 52, 45, 53, 49, 50, 52, 101, 101, 52, 53, 45, 101, 57, 52, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 53, 99, 51, 55, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 101, 57, 52, 45, 51, 48, 51, 98, 98, 100, 50, 102, 45, 101, 57, 52, 10, 67, 83, 101, 113, 58, 32, 49, 32, 67, 65, 78, 67, 69, 76, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 112, 111, 114, 116, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 101, 57, 52, 45, 51, 56, 102, 50, 50, 101, 45, 53, 100, 55, 54, 100, 102, 101, 97, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 55, 48, 10, 83, 117, 112, 112, 111, 114, 116, 101, 100, 58, 32, 114, 101, 112, 108, 97, 99, 101, 115, 44, 49, 48, 48, 114, 101, 108, 44, 101, 118, 101, 110, 116, 108, 105, 115, 116, 44, 116, 105, 109, 101, 114, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
//21.200OK.txt
// sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 50, 48, 48, 32, 79, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 101, 57, 52, 45, 51, 56, 102, 50, 50, 101, 45, 53, 100, 55, 54, 100, 102, 101, 97, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 49, 57, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 101, 57, 52, 45, 53, 49, 50, 52, 101, 101, 52, 53, 45, 101, 57, 52, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 53, 48, 51, 49, 55, 48, 52, 55, 49, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 53, 99, 51, 55, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 101, 57, 52, 45, 51, 48, 51, 98, 98, 100, 50, 102, 45, 101, 57, 52, 10, 67, 83, 101, 113, 58, 32, 49, 32, 67, 65, 78, 67, 69, 76, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
//22.487RequestTerminate.txt
sipByteArray := []byte{83, 73, 80, 47, 50, 46, 48, 32, 52, 56, 55, 32, 82, 101, 113, 117, 101, 115, 116, 32, 84, 101, 114, 109, 105, 110, 97, 116, 101, 100, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 101, 99, 101, 105, 118, 101, 100, 61, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 59, 114, 112, 111, 114, 116, 61, 53, 48, 54, 48, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 101, 57, 52, 45, 51, 56, 102, 50, 50, 101, 45, 53, 100, 55, 54, 100, 102, 101, 97, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 49, 57, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 101, 57, 52, 45, 53, 49, 50, 52, 101, 101, 52, 53, 45, 101, 57, 52, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 53, 48, 51, 49, 55, 48, 52, 55, 49, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 53, 99, 51, 55, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 101, 57, 52, 45, 51, 48, 51, 98, 98, 100, 50, 102, 45, 101, 57, 52, 10, 67, 83, 101, 113, 58, 32, 49, 32, 73, 78, 86, 73, 84, 69, 10, 83, 101, 114, 118, 101, 114, 58, 32, 77, 56, 48, 48, 66, 47, 118, 46, 55, 46, 50, 48, 65, 46, 50, 48, 52, 46, 55, 53, 57, 10, 82, 101, 97, 115, 111, 110, 58, 32, 83, 73, 80, 32, 59, 99, 97, 117, 115, 101, 61, 52, 56, 55, 32, 59, 116, 101, 120, 116, 61, 34, 52, 56, 55, 32, 82, 101, 113, 117, 101, 115, 116, 32, 84, 101, 114, 109, 105, 110, 97, 116, 101, 100, 34, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
//23.ACK.txt
// sipByteArray := []byte{65, 67, 75, 32, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 32, 83, 73, 80, 47, 50, 46, 48, 10, 70, 114, 111, 109, 58, 32, 34, 57, 48, 48, 49, 34, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 55, 52, 101, 49, 57, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 101, 57, 52, 45, 53, 49, 50, 52, 101, 101, 52, 53, 45, 101, 57, 52, 10, 84, 111, 58, 32, 60, 115, 105, 112, 58, 48, 49, 48, 52, 55, 49, 53, 48, 52, 50, 50, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 50, 50, 50, 58, 53, 48, 57, 48, 62, 59, 116, 97, 103, 61, 49, 99, 53, 48, 51, 49, 55, 48, 52, 55, 49, 10, 67, 97, 108, 108, 45, 73, 68, 58, 32, 55, 53, 99, 51, 55, 56, 45, 98, 53, 48, 48, 97, 56, 99, 48, 45, 49, 51, 99, 52, 45, 53, 53, 48, 49, 51, 45, 101, 57, 52, 45, 51, 48, 51, 98, 98, 100, 50, 102, 45, 101, 57, 52, 10, 67, 83, 101, 113, 58, 32, 49, 32, 65, 67, 75, 10, 86, 105, 97, 58, 32, 83, 73, 80, 47, 50, 46, 48, 47, 85, 68, 80, 32, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 58, 53, 48, 54, 48, 59, 114, 112, 111, 114, 116, 59, 98, 114, 97, 110, 99, 104, 61, 122, 57, 104, 71, 52, 98, 75, 45, 101, 57, 52, 45, 51, 56, 102, 50, 50, 101, 45, 53, 100, 55, 54, 100, 102, 101, 97, 10, 77, 97, 120, 45, 70, 111, 114, 119, 97, 114, 100, 115, 58, 32, 55, 48, 10, 65, 108, 108, 111, 119, 58, 32, 82, 69, 71, 73, 83, 84, 69, 82, 44, 32, 73, 78, 86, 73, 84, 69, 44, 32, 65, 67, 75, 44, 32, 66, 89, 69, 44, 32, 82, 69, 70, 69, 82, 44, 32, 78, 79, 84, 73, 70, 89, 44, 32, 67, 65, 78, 67, 69, 76, 44, 32, 73, 78, 70, 79, 44, 32, 79, 80, 84, 73, 79, 78, 83, 44, 32, 80, 82, 65, 67, 75, 44, 32, 83, 85, 66, 83, 67, 82, 73, 66, 69, 44, 32, 85, 80, 68, 65, 84, 69, 44, 32, 80, 85, 66, 76, 73, 83, 72, 10, 85, 115, 101, 114, 45, 65, 103, 101, 110, 116, 58, 32, 65, 85, 68, 67, 45, 73, 80, 80, 104, 111, 110, 101, 47, 50, 46, 50, 46, 49, 50, 46, 49, 55, 50, 32, 40, 52, 48, 53, 45, 82, 101, 118, 50, 59, 32, 48, 48, 57, 48, 56, 70, 66, 66, 54, 53, 54, 49, 41, 10, 67, 111, 110, 116, 97, 99, 116, 58, 32, 60, 115, 105, 112, 58, 57, 48, 48, 49, 64, 49, 57, 50, 46, 49, 54, 56, 46, 48, 46, 49, 56, 49, 62, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 48, 10, 10}
sip := NewSIP()
sip.SipParser(sipByteArray)
fmt.Printf("sip %+v\n\n", sip)
if sip.Content != nil {
fmt.Printf("sdp %+v\n\n", sip.Content)
fmt.Printf("sdp media %+v\n\n", sip.Content.Media)
}
// assert.Equal(t, "INVITE", sip.Method, "not expected value")
/*
value := "audio 7830 RTP/AVP 8 0 18 101"
spaceSplitValue := strings.Split(value, " ")
for i, fieldValue := range spaceSplitValue {
intValue, err := strconv.Atoi(strings.TrimSpace(fieldValue))
if i >= 3 && err == nil {
fmt.Println(intValue)
}
}
*/
// a := 0 // register
// a = 11264 // invite
// a = 11264 // prack
// a = 2048 // ack
// a = 0 // bye
// a = 3072 // cancel
fmt.Printf("%016b\n", ICS_SIP_AUTOMATA_INVITE)
// b := 1
fmt.Printf("%016b\n", ICS_SIP_AUTOMATA_INVITE&ICS_SIP_JOB_TYPE_ACK)
}
const (
ICS_SIP_AUTOMATA_INVITE = 11264
ICS_SIP_AUTOMATA_ACK = 2048
ICS_SIP_AUTOMATA_CANCEL = 3072
)
const (
ICS_SIP_JOB_TYPE_REGISTER = 1 << iota
ICS_SIP_JOB_TYPE_INVITE
ICS_SIP_JOB_TYPE_PUBLISH
ICS_SIP_JOB_TYPE_OPTIONS
ICS_SIP_JOB_TYPE_INFO
ICS_SIP_JOB_TYPE_UPDATE
ICS_SIP_JOB_TYPE_REFFER
ICS_SIP_JOB_TYPE_SUBSCRIBE
ICS_SIP_JOB_TYPE_MESSAGE
ICS_SIP_JOB_TYPE_NOTIFY
ICS_SIP_JOB_TYPE_PRACK
ICS_SIP_JOB_TYPE_ACK
ICS_SIP_JOB_TYPE_BYE
ICS_SIP_JOB_TYPE_CANCEL
)

@ -0,0 +1,104 @@
package icsrtp
import (
"encoding/binary"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)
type RTP struct {
Version int
Mark int
PayloadType icspacketparser.PayloadType
Seq uint16
Timestamp uint32
SSID uint32
PayloadLen int
Payload []byte
RtpHeaderByte []byte
}
const RTPHeaderLen = 12
func NewRTP(mark, pt, seq, ts, ssrc int, payload []byte) *RTP {
rtp := RTP{}
rtp.RtpHeaderByte = make([]byte, RTPHeaderLen)
//version, padding, extension, cc
rtp.RtpHeaderByte[0] = 0x80
//fmt.Printf("v %b\n", rtp.RtpHeaderByte[0])
//mark, payload type
m := byte(0xff & (mark << 7))
p := byte(0xff) & byte(pt)
rtp.RtpHeaderByte[1] = m | p
/*
fmt.Printf("m %b\n", m)
fmt.Printf("p %b\n", p)
*/
//sequence
o := make([]byte, 4)
binary.BigEndian.PutUint16(o, uint16(seq))
//o := ByteOrdering(uint(seq), 2, true)
/*
rtp.RtpHeaderByte[2] = o[1]
rtp.RtpHeaderByte[3] = o[0]
*/
copy(rtp.RtpHeaderByte[2:4], o[:2])
//fmt.Printf("seq: %d - %d|%d\n", seq, o[0], o[1])
/*
fmt.Printf("seq: %d - %d[%b]\n",
uint(seq),
uint16(rtp.RtpHeaderByte[2])|uint16(rtp.RtpHeaderByte[3])<<8,
uint16(rtp.RtpHeaderByte[2])|uint16(rtp.RtpHeaderByte[3])<<8)
*/
//timestamp
//o = ByteOrdering(uint(ts), 4, true)
binary.BigEndian.PutUint32(o, uint32(ts))
/*
rtp.RtpHeaderByte[4] = o[3]
rtp.RtpHeaderByte[5] = o[2]
rtp.RtpHeaderByte[6] = o[1]
rtp.RtpHeaderByte[7] = o[0]
*/
copy(rtp.RtpHeaderByte[4:8], o[:])
/*
fmt.Printf("time now %d, %d\n",
uint32(ts),
uint32(rtp.RtpHeaderByte[4])|uint32(rtp.RtpHeaderByte[5])<<8|uint32(rtp.RtpHeaderByte[6])<<16|uint32(rtp.RtpHeaderByte[7])<<24)
*/
//ssrc
//o = ByteOrdering(uint(ssrc), 4, true)
binary.BigEndian.PutUint32(o, uint32(ssrc))
/*
rtp.RtpHeaderByte[8] = o[3]
rtp.RtpHeaderByte[9] = o[2]
rtp.RtpHeaderByte[10] = o[1]
rtp.RtpHeaderByte[11] = o[0]
*/
copy(rtp.RtpHeaderByte[8:], o[:])
/*
fmt.Printf("ssrc %x, %x\n",
uint32(ssrc),
uint32(rtp.RtpHeaderByte[8])|uint32(rtp.RtpHeaderByte[9])<<8|uint32(rtp.RtpHeaderByte[10])<<16|uint32(rtp.RtpHeaderByte[11])<<24)
*/
rtp.Payload = make([]byte, len(payload))
copy(rtp.Payload, payload)
return &rtp
}
func (r RTP) Byte() []byte {
payloadLen := len(r.Payload)
ret := make([]byte, payloadLen+RTPHeaderLen)
offset := copy(ret, r.RtpHeaderByte)
copy(ret[offset:], r.Payload)
return ret
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,153 @@
/*
Call Signal Processor
*/
package icssessionmanager
import (
"time"
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
parser "gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)
func (s *IcsSession) Processing(sip *parser.SIP) *icserror.IcsError {
if sip == nil {
return icserror.ICSERRInvalidParam
}
l := icslog.GetIcsLog()
conf := icsconf.GetIcsConfig()
switch sip.Method {
case parser.ICS_SIP_METHOD_REGISTER:
return s.ProcRegister(sip)
case parser.ICS_SIP_METHOD_INVITE:
l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "INVITE")
//time.Sleep(3000 * time.Millisecond)
//return nil
return s.ProcInvite(sip)
case parser.ICS_SIP_METHOD_PUBLISH:
case parser.ICS_SIP_METHOD_OPTIONS:
case parser.ICS_SIP_METHOD_INFO:
case parser.ICS_SIP_METHOD_UPDATE:
case parser.ICS_SIP_METHOD_REFER:
case parser.ICS_SIP_METHOD_SUBSCRIBE:
case parser.ICS_SIP_METHOD_MESSAGE:
case parser.ICS_SIP_METHOD_NOTIFY:
s.ProcReferNotify200ok(sip)
case parser.ICS_SIP_METHOD_PRACK:
case parser.ICS_SIP_METHOD_ACK:
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "ACK - %+v", sip)
s.InviteSIP = sip
if s.GetAgentStatus() == STATUS_AGENT_CALLING {
s.SetAgentStatus(STATUS_AGENT_BUSY)
//s.RTPSenderCallBackTimer.Start()
//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started [%s]RTP callback timer", conf.AgentConfig[s.ID].Name)
} else if s.GetAgentStatus() == STATUS_AGENT_ERROR {
s.RequestBYE(s.InviteSIP)
s.SetAgentStatus(STATUS_AGENT_READY)
}
/*else {
l.Print(icslog.LOG_LEVEL_INFO, s.ID, "ACK")
}
*/
case parser.ICS_SIP_METHOD_BYE:
l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "BYE")
status := s.GetAgentStatus()
if status == STATUS_AGENT_BUSY {
s.RTPSenderCallBackTimer.Stop()
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Stoped [%s] RTP callback timer", conf.AgentConfig[s.ID].Name)
}
err := s.ProcBye(sip)
if err != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not process BYE method - %s", err.GetMessage())
}
s.RemoveSession()
//////////////////////////////////
//////// for simul //////////////
//////////////////////////////////
// send 83 to reg200
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Start Sim!!!")
time.Sleep(time.Second)
s.SendRequestInvite()
//////////////////////////////////
//////////////////////////////////
//////////////////////////////////
case parser.ICS_SIP_METHOD_CANCEL:
s.RTPSenderCallBackTimer.Stop()
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Stoped [%s] RTP callback timer", conf.AgentConfig[s.ID].Name)
err := s.ProcCancel(sip)
if err != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not process CANCEL method - %s", err.GetMessage())
}
case parser.ICS_SIP_METHOD_SIP20: //recved response proc
switch GetJobType(sip) {
case ICS_SIP_JOB_TYPE_REGISTER:
//check status code
code := sip.Source
if strings.Compare(code, "200") == 0 {
s.SetRegisterStatus(STATUS_REGISTER_REGISTERED)
s.SetAgentStatus(STATUS_AGENT_READY)
//s.INVITECallBackTimer.Start()
//defer s.INVITECallBackTimer.Stop()
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Agent [%s] registered [%s]", s.AgentName, s.callID)
s.RemoveSession()
}
case ICS_SIP_JOB_TYPE_INVITE:
//l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "sip20 invite - %s", sip.Source)
code := sip.Source
switch code {
case "100":
case "180":
case "183":
case "200":
//response ACK
s.ProcACKInvite(sip)
default:
//response ACK
s.ProcACKInvite(sip)
}
case ICS_SIP_JOB_TYPE_PUBLISH:
case ICS_SIP_JOB_TYPE_OPTIONS:
s.RequestInvite("01024342788")
case ICS_SIP_JOB_TYPE_INFO:
case ICS_SIP_JOB_TYPE_UPDATE:
case ICS_SIP_JOB_TYPE_REFER:
case ICS_SIP_JOB_TYPE_SUBSCRIBE:
case ICS_SIP_JOB_TYPE_MESSAGE:
case ICS_SIP_JOB_TYPE_NOTIFY:
case ICS_SIP_JOB_TYPE_PRACK:
case ICS_SIP_JOB_TYPE_ACK:
case ICS_SIP_JOB_TYPE_BYE:
if s.GetAgentStatus() == STATUS_AGENT_BUSY || s.GetAgentStatus() == STATUS_AGENT_BYEING {
s.ProcSIP20Bye(sip)
}
case ICS_SIP_JOB_TYPE_CANCEL:
/*
//check status code
code := sip.Source
if strings.Compare(code, "200") == 0 {
s.SetAgentStatus(STATUS_AGENT_READY)
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Agent [%s] CANCELed", s.AgentName)
}
*/
default:
}
case parser.ICS_SIP_METHOD_NOT_FOUND:
default:
}
return nil
}

@ -0,0 +1,77 @@
package icssessionmanager
import (
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
"gitlab.com/ics_cinnamon/voicegateway/recorddata"
)
func (s *IcsSession) analyzeRTP(rtp *icspacketparser.RTP) *icserror.IcsError {
l := icslog.GetIcsLog()
RPT := rtp.GetPayloadType()
SPT := s.GetPayloadType()
if SPT == RPT {
if s.VoiceNeter == nil {
l.Print(icslog.LOG_LEVEL_ERROR, s.ID, icserror.ICSERRNETNotConnectError.GetMessage())
return icserror.ICSERRNETNotConnectError
}
voicedata := recorddata.NewVoiceData()
svc := icssvc.GetServiceStatus()
conf := svc.GetIcsConfig()
if strings.Compare(conf.PbxConfig.PbxIp, rtp.SrcAddr.IPv4String) == 0 { //RX
/*//////////////////
s.rxFile.Write(rtp.Payload)
*/ //////////////////
pcm, err := s.RxConverter.Decode(rtp.Payload)
if err != nil {
l.Print(icslog.LOG_LEVEL_ERROR, s.ID, err.GetMessage())
return err
}
if s.rxSeq == -1 {
s.rxSeq = int(rtp.Seq)
}
voicedata.SetData(s.ServerID, s.Station, int32(rtp.Seq-uint16(s.rxSeq)), s.StartTimeStamp, "0", rtp.GetPayloadType(), pcm)
//voicedata.SetData(s.ServerID, s.Station, int32(rtp.Seq-uint16(s.rxSeq)), s.StartTimeStamp, "0", "0", pcm)
wsize, err := s.VoiceNeter.Write(voicedata.GetData())
if wsize == -1 || err != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "RTP send error-%v", err.GetError())
return err
}
} else { //TX
/*//////////////////
s.txFile.Write(rtp.Payload)
*/ //////////////////
pcm, err := s.TxConverter.Decode(rtp.Payload)
if err != nil {
l.Print(icslog.LOG_LEVEL_ERROR, s.ID, err.GetMessage())
return err
}
if s.txSeq == -1 {
s.txSeq = int(rtp.Seq)
}
voicedata.SetData(s.ServerID, s.Station, int32(rtp.Seq-uint16(s.txSeq)), s.StartTimeStamp, "1", rtp.GetPayloadType(), pcm)
//voicedata.SetData(s.ServerID, s.Station, int32(rtp.Seq-uint16(s.txSeq)), s.StartTimeStamp, "1", "0", pcm)
wsize, err := s.VoiceNeter.Write(voicedata.GetData())
if wsize == -1 || err != nil {
//l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "RTP send error-%v", err.GetError())
return err
}
}
} else {
l.Print(icslog.LOG_LEVEL_ERROR, s.ID, "NO same payload type!!!")
}
return nil
}

@ -0,0 +1,225 @@
package icssessionmanager
import (
"strconv"
"strings"
"time"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icsmediaconv"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
"gitlab.com/ics_cinnamon/voicegateway/recorddata/writecallsignal"
)
func (s *IcsSession) analyzeSIP(sip *icspacketparser.SIP) *icserror.IcsError {
// fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>")
// fmt.Println("sip.Method", sip.Method)
// fmt.Println("sip.Version", sip.Version)
// fmt.Println("sip.Headers", sip.Headers)
// fmt.Println("sip.Source", sip.Source)
// fmt.Printf("%+v\n", sip)
//fmt.Println(">>>>>>>>>>>>>>>>>>>>>>> sip.Method", sip.Method)
l := icslog.GetIcsLog()
// fmt.Println(">>>>>>>>>>>>>>>>>>>>>>> sip.Method", sip.Method)
if sip.Method == icspacketparser.ICS_SIP_METHOD_INVITE {
s.setSrcPort(sip)
payload, err := s.setSDPMediaPayload(sip)
if err != nil {
return icserror.ICSERRSDPAudiotagPortValue
} else {
s.invitePayloads = payload
}
} else if strings.Contains(sip.Cseq, " INVITE") {
s.setDstPort(sip)
}
if sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 && !s.isFoundPayload {
// fmt.Println(">>>>>>>>>>>>>>> ICS_SIP_METHOD_SIP20", sip.ResType, sip.ContentType, sip.ContentLength)
if strings.Contains(sip.ContentType, "sdp") && sip.ContentLength > 0 {
payload, err := s.compareSDPMediaPayload(sip)
if err != nil {
return icserror.ICSERRSDPAudiotagPortValue
} else {
s.isFoundPayload = true
s.payloadType = icspacketparser.PayloadType(payload)
//fmt.Println("s.payload >>>>>>>>>>>>>>>", s.payloadType)
//create media decoder
var cerr *icserror.IcsError
s.TxConverter, cerr = icsmediaconv.NewConverter(s.ID, s.payloadType, true)
if cerr != nil {
//s.isFoundPayload = false
//cerr.Print()
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to New Tx Converter-%v", cerr)
return cerr
} else {
l.Print(icslog.LOG_LEVEL_INFO, s.ID, "New Tx Converter(Decoder)")
}
s.RxConverter, cerr = icsmediaconv.NewConverter(s.ID, s.payloadType, true)
if cerr != nil {
//s.isFoundPayload = false
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to New Rx Converter-%v", cerr)
return cerr
} else {
l.Print(icslog.LOG_LEVEL_INFO, s.ID, "New Rx Converter(Decoder)")
}
//init VoiceAgent net and send call start signal
conf := icssvc.GetServiceStatus().GetIcsConfig()
if conf != nil {
/*
csraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentInfo[s.ID].IP, conf.VoiceAgentConfig.AgentInfo[s.ID].Port)
csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
//set Voice addr
vraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentInfo[s.ID].IP, conf.VoiceAgentConfig.AgentInfo[s.ID].VoicePort)
*/
//set call signal addr
csraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentInfo[s.ID].IP, conf.VoiceAgentConfig.AgentInfo[s.ID].Port)
csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
//csraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentAddr.VoiceAgentIP, conf.VoiceAgentConfig.AgentAddr.CallSignalPort)
//csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
//set Voice addr
vraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentInfo[s.ID].IP, conf.VoiceAgentConfig.AgentInfo[s.ID].VoicePort)
//vraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentAddr.VoiceAgentIP, s.VoiceAgentPort)
//vraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentAddr.VoiceAgentIP, conf.VoiceAgentConfig.AgentAddr.VoicePort)
//vladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.BasePort)
s.VoiceNeter = icsnet.NewUDP(nil, &vraddr)
//s.VoiceNeter = icsnet.NewUDP(&vladdr, &vraddr)
conerr := s.VoiceNeter.Connect(nil, nil)
if conerr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Error init Voice Neter[%s->%s]-%v", s.VoiceNeter.LocalAddr().String(), vraddr.String(), conerr.GetError())
return conerr
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Voice(UDP) Connected to VoiceAgent[%s->%s]", s.VoiceNeter.LocalAddr().String(), vraddr.String())
//send call signal data to VoiceAgent
defer func() {
if err := recover(); err != nil {
l.Print(icslog.LOG_LEVEL_WARN, s.ID, icserror.ICSERRNETNotConnectError.GetMessage())
}
}()
var inout string = "O"
if s.GetDirection() {
inout = "I"
}
callsignal := writecallsignal.NewCallSignalData()
s.StartTimeStamp = time.Now().UnixNano()
callsignal.SetData(s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, 0, "S", inout)
t, wlen, werr := icsnet.SendCallSignal(&csladdr, &csraddr, callsignal.GetData())
if werr == nil {
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Transmitted Call-Start signal to VoiceAgent(%d)", wlen)
if t != nil {
t.Close()
}
}
t.Close()
}
}
}
}
return nil
}
func (s *IcsSession) setSrcPort(sip *icspacketparser.SIP) *icserror.IcsError {
if sip.Content == nil {
//error 처리 invite인데, sdp 데이터가 없음
return icserror.ICSERRINVITERequired
} else {
// fmt.Println("sdpMedias", *sip.Content.Media)
port, err := s.findSDPMediaAudioPort(sip)
if err != nil {
return icserror.ICSERRSDPAudiotagPortValue
} else {
s.srcPort = port
}
}
return nil
}
func (s *IcsSession) setDstPort(sip *icspacketparser.SIP) *icserror.IcsError {
// fmt.Println(">>>>>>>>>>>>>>>>>>>>>>> sip.Cseq", sip.Cseq, sip.Method)
if sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 && sip.ResType == "200" {
if sip.Content == nil {
//error 처리 INVITE처리의 200 OK인데, sdp 데이터가 없음
return icserror.ICSERR200OKRequired
} else {
// fmt.Println("sdpMedias", *sip.Content.Media)
port, err := s.findSDPMediaAudioPort(sip)
if err != nil {
return icserror.ICSERRSDPAudiotagPortValue
} else {
s.dstPort = port
}
}
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_BYE {
//fmt.Println(">>>>>>>>>>> haup up event")
// s.RemoveSession()
}
return nil
}
func (s *IcsSession) findSDPMediaAudioPort(sip *icspacketparser.SIP) (int, *icserror.IcsError) {
for _, value := range *sip.Content.Media {
if strings.Contains(value.MediaDescription, "audio ") {
arrSdpMedia := strings.Split(value.MediaDescription, " ")
port, err := strconv.Atoi(arrSdpMedia[1])
if err != nil {
return -1, icserror.ICSERRSDPAudiotagPortValue
} else {
//fmt.Println(">>>>>>>>>>>>>>>>>>>>>>> port", port)
return port, nil
}
} else {
return -1, icserror.ICSERRNotFoundSdpMedia
}
}
return -1, icserror.ICSERRNotFoundSdpMedia
}
func (s *IcsSession) setSDPMediaPayload(sip *icspacketparser.SIP) ([]string, *icserror.IcsError) {
for _, value := range *sip.Content.Media {
if strings.Contains(value.MediaDescription, "audio ") {
//fmt.Println("value.Payload >>>>>>>>>>>", value.Payload)
return value.Payload, nil
} else {
return nil, icserror.ICSERRNotFoundSdpMedia
}
}
return nil, icserror.ICSERRNotFoundSdpMedia
}
func (s *IcsSession) compareSDPMediaPayload(sip *icspacketparser.SIP) (int, *icserror.IcsError) {
for _, value := range *sip.Content.Media {
for _, thisPayload := range value.Payload {
for _, invitePayload := range s.invitePayloads {
ptNum, cerr := strconv.Atoi(thisPayload)
if cerr != nil {
return -1, icserror.ICSERRSDPAudiotagPortValue
}
name := icspacketparser.RTPPayloadInfo[icspacketparser.PayloadType(ptNum)].Name
if name == invitePayload {
//if thisPayload == invitePayload {
payload, err := strconv.Atoi(thisPayload)
if err != nil {
return -1, icserror.ICSERRSDPAudiotagPortValue
} else {
return payload, nil
}
}
}
}
}
return -1, icserror.ICSERRNotFoundSdpMedia
}

@ -0,0 +1,315 @@
package icssessionmanager
import (
"fmt"
"strings"
"sync"
"time"
"gitlab.com/ics_cinnamon/joy4/format"
"gitlab.com/ics_cinnamon/voicegateway/icscbtimer"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icsdtmf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icsevent"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icsmediaconv"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
)
type IcsSession struct {
ID int
goroutineID int
//agent config
AgentInfo *icsconf.AgentInfo
AgentConf *icsconf.AgentConfig
sipNeter *icsnet.IcsNeter
callID string
//regiCallID string
uri string //register from
srcPort int
dstPort int
direction bool
eventSystem *icsevent.EventSystem
//manage session
lastTimestamp time.Time
isStart bool
//media
invitePayloads []string
payloadType icspacketparser.PayloadType
isFoundPayload bool
TxConverter *icsmediaconv.Converter
RxConverter *icsmediaconv.Converter
txSeq int //first TX seq num
rxSeq int //first RX seq num
RTPCBStatus int
//TTS data
tts []byte
//call info
StartTimeStamp int64
EndTimeStamp int64
Station string
ChannelID string
ServerID int
CustID string
/*//////////////////
rxFile *os.File
txFile *os.File
*/ //////////////////
//Voice agent conn
//CallSignalNeter icsnet.IcsNeter
VoiceNeter icsnet.IcsNeter
MethodAutomata int
//agent
AgentName string
AgentName2 string
//RTP port
RTPPort int
//register callback timer
RegisterCallBackTimer *icscbtimer.IcsCBTimer
registerStatus int
agentStatus int
//OPTIONS callback timer
OPTIONSCallBackTimer *icscbtimer.IcsCBTimer
//RTP sender callback timer
RTPSenderCallBackTimer *icscbtimer.IcsCBTimer
//INVITE callback timer
INVITECallBackTimer *icscbtimer.IcsCBTimer
//rtp/rtcp Tx/Rx neter
/*
rtpTxPort int
rtpTxIP string
rtpTxAddr *icsnet.IcsNetAddr
rtcpTxPort int
rtcpTxIP string
rtcpTxAddr *icsnet.IcsNetAddr
rtpTxNeter icsnet.IcsNeter
rtcpTxNeter icsnet.IcsNeter
*/
//remoteMediaAddr *icsnet.IcsNetAddr
rtpMediaNeter icsnet.IcsNeter
rtcpMediaNeter icsnet.IcsNeter
//media format
mediaFormat []string
//rtp info
rtpSSRC uint32
rtpSeq uint16
rtpTS uint32
//call statistic
rxCnt int
txCnt int
callStartTime time.Time
callEndTime time.Time
//cseq
Cseq uint32
RegiCseq uint32
CurrentSIP *icspacketparser.SIP
InviteSIP *icspacketparser.SIP
//dtmf handle
dtmf *icsdtmf.ICSDTMF
// botStatus
BotStatus uint32
//tmp refer to
referto string
simLoopCount int
// ExpTimer *icscbtimer.IcsCBTimer
expRead time.Time
readTimer time.Ticker
expCheck bool
mychannel chan bool
m *sync.Mutex
}
type IcsSessionID int
const MAX_SESSION_IDLE = time.Hour
const (
ICS_INBOUND_CALL = true
ICS_OUTBOUND_CALL = false
)
//////////////////////////////////////////////////////////////////
//session routine
//init ffmpeg
func init() {
format.RegisterAll()
}
//on/off check the session idle
func (s *IcsSession) Start() {
s.SetTimestamp(time.Now())
s.isStart = true
}
func (s *IcsSession) Stop() {
l := icslog.GetIcsLog()
l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Session Stop")
s.isStart = false
}
func (s *IcsSession) Init() *icserror.IcsError {
l := icslog.GetIcsLog()
//conf := icsconf.GetIcsConfig()
s.RTPCBStatus = 0
/*
s.AgentName = s.AgentConf.Name
s.AgentName2 = fmt.Sprintf("agent%s", s.AgentConf.Name)
*/
//media format
s.mediaFormat = strings.Split(s.AgentConf.MediaConfig.Format, " ")
//s.mediaFormat = strings.Split(conf.AgentConfig[s.ID].MediaConfig.Format, " ")
//fmt.Println(len(s.mediaFormat), s.mediaFormat)
//create rx rtp/rtcp listener
s.RTPPort = s.AgentConf.MediaConfig.Port
if s.rtpMediaNeter == nil {
//s.RTPPort = conf.AgentConfig[s.ID].MediaConfig.Port
RTPAddrStr := fmt.Sprintf("0.0.0.0:%d", s.RTPPort)
RTPAddr := icsnet.NewNetAddrWithIPAddr(RTPAddrStr)
s.rtpMediaNeter = icsnet.NewUDP(&RTPAddr, nil)
RTCPAddrStr := fmt.Sprintf("0.0.0.0:%d", s.RTPPort+1)
RTCPAddr := icsnet.NewNetAddrWithIPAddr(RTCPAddrStr)
s.rtcpMediaNeter = icsnet.NewUDP(&RTCPAddr, nil)
//set rtp send callback
s.RTPPort = s.AgentConf.MediaConfig.Port
s.RTPSenderCallBackTimer = icscbtimer.NewCBTimer(time.Millisecond*20, s.SendRTPCB)
err1 := s.rtpMediaNeter.Listen()
if err1 != nil {
l.Print(icslog.LOG_LEVEL_FATAL, s.ID, err1.GetMessage())
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "%s", err1.GetError())
return err1
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Listening RTP port[%d]", s.RTPPort)
err1 = s.rtcpMediaNeter.Listen()
if err1 != nil {
l.Print(icslog.LOG_LEVEL_FATAL, s.ID, err1.GetMessage())
return err1
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Listening RTCP port[%d]", s.RTPPort+1)
s.dtmf = icsdtmf.NewICSDTMF()
go s.ReadRTP()
go s.ReadRTCP()
}
return nil
}
func (s *IcsSession) Run() *icserror.IcsError {
mySessionID := s.GetSessionID()
l := icslog.GetIcsLog()
conf := icsconf.GetIcsConfig()
s.goroutineID = goid()
l.Printf(icslog.LOG_LEVEL_DEBUG2, int(mySessionID), "Session [%d] READY\n", mySessionID)
//start callback timer func
if strings.Compare(strings.ToUpper(conf.AgentConfig[s.ID].Value), "TRUE") == 0 {
s.SetRegisterStatus(STATUS_REGISTER_READY)
s.RegisterCallBackTimer.Start()
defer s.RegisterCallBackTimer.Stop()
s.OPTIONSCallBackTimer.Start()
defer s.OPTIONSCallBackTimer.Stop()
//s.INVITECallBackTimer.Start()
//defer s.INVITECallBackTimer.Stop()
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started [%s] callback timer", conf.AgentConfig[s.ID].Name)
}
svc := icssvc.GetServiceStatus()
for !svc.GetExit() && !svc.GetStop() {
//get event
h := icsevent.NewEventH()
evt, evterr := h.GetEvent(int(mySessionID))
if evt == nil {
if evterr != nil {
//evterr.Print()
time.Sleep(time.Millisecond)
continue
}
if strings.Compare(strings.ToUpper(conf.AgentConfig[s.ID].Value), "TRUE") == 0 {
duration := time.Since(s.lastTimestamp)
if s.isStart && duration >= MAX_SESSION_IDLE {
//Session expired!
err := icserror.ICSERRSESSMaxSessionIdle
logmsg := fmt.Sprintf("Session expired. Duration: %v(%v) - %s\n", duration, s.lastTimestamp, err.GetMessage())
l.Print(icslog.LOG_LEVEL_INFO, s.ID, logmsg)
s.Stop()
serr := s.RemoveSession()
if serr != nil {
//serr.Print()
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "RemoveSession Error %s", serr.GetMessage())
}
//return err
}
}
time.Sleep(time.Millisecond)
continue
}
//refresh session timestamp
s.SetTimestamp(time.Now())
//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Get Event[%d]", evt.ID)
data := evt.GetData()
switch v := (*data).(type) {
case icspacketparser.SIP:
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Get SIP Event[%d]", evt.ID)
sip := v
s.CurrentSIP = &sip
s.Processing(&sip)
//s.analyzeSIP(&sip)
case icspacketparser.RTP:
//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Get RTP Event[%d]", evt.ID)
rtp := v
//fmt.Println(rtp)
s.analyzeRTP(&rtp)
default:
fmt.Println(time.Now(), "NOT DEFINED EVENT TYPE!!!!!!!!!!!!!!!!!")
}
}
l.Print(icslog.LOG_LEVEL_DEBUG2, s.ID, "Stoped Session!")
return nil
}

@ -0,0 +1,563 @@
package icssessionmanager
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"strings"
"sync"
"time"
"gitlab.com/ics_cinnamon/voicegateway/icscbtimer"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icsevent"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
"gitlab.com/ics_cinnamon/voicegateway/recorddata"
)
type SessionManager struct {
evtSystem []*icsevent.EventSystem
sessions []*IcsSession
event *icsevent.EventH
//sip listener
SIPNeter icsnet.IcsNeter
//bot-command net
CommNet *icsnet.IcsTCPNet
}
var bigSession []*IcsSession
//var bigSession []*IcsSession
var onceSession sync.Once
var channelNum int
func getSessionInstance(SIPNeter *icsnet.IcsNeter) []*IcsSession {
//l := icslog.GetIcsLog()
onceSession.Do(func() {
bigSession = make([]*IcsSession, channelNum)
svc := icssvc.GetServiceStatus()
conf := svc.GetIcsConfig()
agentNum := len(conf.AgentConfig)
for iter := 0; iter < channelNum; iter++ {
bigSession[iter] = new(IcsSession)
bigSession[iter].m = &sync.Mutex{}
bigSession[iter].ID = iter
//bigSession[iter].goroutineID = goid()
bigSession[iter].isStart = false
//bigSession[iter].lastTimestamp = time.Now()
bigSession[iter].Cseq = 0
bigSession[iter].registerStatus = STATUS_REGISTER_NOT_READY
bigSession[iter].agentStatus = STATUS_AGENT_NOT_READY
bigSession[iter].AgentName = conf.AgentConfig[iter].Name
bigSession[iter].simLoopCount = 1
bigSession[iter].AgentName2 = fmt.Sprintf("agent%s", conf.AgentConfig[iter].Name)
if iter < agentNum {
if strings.Contains(strings.ToUpper(conf.AgentConfig[iter].Value), "TRUE") {
/*
//set rtp send callback
bigSession[iter].RTPPort = conf.AgentConfig[iter].MediaConfig.Port
bigSession[iter].RTPSenderCallBackTimer =
icscbtimer.NewCBTimer(
time.Millisecond*20,
bigSession[iter].SendRTPCB)
//set session's agentInfo conf
agentInfo := bigSession[iter].FindAgentInfo(bigSession[iter].AgentName)
if agentInfo != nil {
bigSession[iter].SetAgentInfo(agentInfo)
}
*/
} else {
bigSession[iter].RTPPort = -1
}
//set register callback timer
if strings.Contains(strings.ToUpper(conf.AgentConfig[iter].RegisterConfig.RegisterValue), "TRUE") {
//bigSession[iter].RegisterCallBackTimer = icscbtimer.NewCBTimer(time.Millisecond*100, bigSession[iter].RequestRegisterCB)
regiExpire := conf.AgentConfig[iter].RegisterConfig.RegisterExpire
bigSession[iter].RegisterCallBackTimer =
icscbtimer.NewCBTimer(
time.Millisecond*1000*time.Duration(regiExpire),
bigSession[iter].RequestRegisterCB)
} else {
bigSession[iter].registerStatus = STATUS_REGISTER_REGISTERED
bigSession[iter].agentStatus = STATUS_AGENT_READY
bigSession[iter].MethodAutomata = 32767
}
//set options callback timer
if strings.Contains(strings.ToUpper(conf.AgentConfig[iter].OptionsConfig.OptionsValue), "TRUE") {
interval := conf.AgentConfig[iter].OptionsConfig.OptionsInterval
bigSession[iter].OPTIONSCallBackTimer =
icscbtimer.NewCBTimer(
time.Millisecond*1000*time.Duration(interval),
bigSession[iter].RequestOptionsCB)
}
/*
//set invite callback timer
bigSession[iter].INVITECallBackTimer =
icscbtimer.NewCBTimer(
time.Millisecond*1000*time.Duration(1),
bigSession[iter].RequestInviteCB)
if err := bigSession[iter].Init(); err != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, -1, "Session Init error. Voice Agent EXIT!! - %s", err.GetMessage())
os.Exit(0)
}
*/
}
bigSession[iter].eventSystem = icsevent.GetMyEventSystem(iter)
//bigSession[iter].Init(iter)
//set sip connection to each sessions
bigSession[iter].sipNeter = SIPNeter
}
})
return bigSession
}
//TODO: make this function to singleton
func NewSessionManager() *SessionManager {
l := icslog.GetIcsLog()
conf := icsconf.GetIcsConfig()
svc := icssvc.NewService()
channelNum = svc.GetIcsConfig().GetChannelNum()
//icsevent.SetConfig(svc.GetIcsConfig())
sm := new(SessionManager)
icsevent.SetChannelNum(channelNum)
sm.evtSystem = icsevent.GetEvtSystemInstance()
//start sip listen
sipPort := conf.SIPConfig.Port
transport := conf.SIPConfig.Transport
sipProxy := conf.SIPConfig.SIPProxy
remoteaddr := icsnet.NewNetAddrWithIPAddr(sipProxy)
localAddrStr := fmt.Sprintf("0.0.0.0:%d", sipPort)
localAddr := icsnet.NewNetAddrWithIPAddr(localAddrStr)
switch strings.ToUpper(transport) {
case "UDP":
sm.SIPNeter = icsnet.NewUDP(&localAddr, &remoteaddr)
case "TCP":
sm.SIPNeter = icsnet.NewTCP(&localAddr, &remoteaddr)
default:
l.Print(icslog.LOG_LEVEL_FATAL, -1, "No compatible transport. Check the configuration")
return nil
}
/*
cerr := sm.SIPNeter.Connect()
if cerr != nil {
l.Print(icslog.LOG_LEVEL_FATAL, -1, cerr.GetMessage())
return nil
}
*/
lerr := sm.SIPNeter.Listen()
if lerr != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, -1, "Listening failed: %s", lerr.GetError())
return nil
}
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening SIP %s port[%d]", transport, sipPort)
/*
//start bot-command listen
commandValue := strings.ToUpper(conf.CommandConfig.Value)
commandPort := conf.CommandConfig.Port
commandTransport := conf.CommandConfig.Transport
if strings.Compare("TRUE", commandValue) == 0 {
commandLocalAddrStr := fmt.Sprintf("0.0.0.0:%d", commandPort)
commandLocalAddr := icsnet.NewNetAddrWithIPAddr(commandLocalAddrStr)
switch strings.ToUpper(commandTransport) {
case "UDP":
sm.CommNeter = icsnet.NewUDP(&commandLocalAddr, nil)
case "TCP":
sm.CommNeter = icsnet.NewTCP(&commandLocalAddr, nil)
default:
l.Print(icslog.LOG_LEVEL_FATAL, -1, "Bot-Command listening error. No compatible transport. Check the configuration")
return nil
}
lerr = sm.CommNeter.Listen()
if lerr != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, -1, "%s", lerr.GetError())
return nil
}
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening Bot-Command %s port[%d]", commandTransport, commandPort)
}
*/
sm.sessions = getSessionInstance(&sm.SIPNeter)
//EventH. Create Event Array
sm.event = icsevent.NewEventH()
return sm
}
func (sm *SessionManager) Load() {
sm.event.Init()
//for iter, session := range sm.sessions {
for _, session := range sm.sessions {
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "333 %d", iter)
go session.Run()
}
}
func (sm *SessionManager) Close() {
for iter := 0; iter < channelNum; iter++ {
sm.sessions[iter].RemoveSession()
}
sm.SIPNeter.Close()
}
func (sm *SessionManager) Run() (icserr *icserror.IcsError) {
l := icslog.GetIcsLog()
conf := icsconf.GetIcsConfig()
svc := icssvc.GetServiceStatus()
for !svc.GetExit() || !svc.GetStop() {
data, addr, len, rerr := sm.SIPNeter.ReadSIP()
if rerr != nil {
return rerr
}
//fmt.Println("RECVED>>>", addr, len, string(data))
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Recved Data[%d] [%s]->[%s]>\n%s",
len,
addr.String(),
sm.SIPNeter.LocalAddr().String(),
string(data[:len]))
sip := icspacketparser.NewSIP()
sip.SipParser(data)
if icspacketparser.ICS_SIP_METHOD_NOT_FOUND == sip.Method { //not found sip. maybe abnormal use
l.Printf(icslog.LOG_LEVEL_INFO, -1, "icspacketparser.ICS_SIP_METHOD_NOT_FOUND-%s", string(data))
continue
} else {
if SessionAvailableSipMethod(&sip) {
l.Printf(icslog.LOG_LEVEL_DEBUG, -1, "Session Processing Method-[%s, %s, %s]",
sip.Method, sip.ResType, sip.Cseq)
s, serr := FindSession(sip)
if serr != nil { //not found session, create new
name1 := strings.SplitN(sip.To, "@", 2)
name2 := strings.SplitN(name1[0], ":", 2)
agentname := name2[1]
s, serr = AllocSession(agentname, sip.GetCallID())
if serr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Licensed Session number[%d:%s] is EXCEEDED-%s",
conf.GetChannelNum(), agentname, serr.GetMessage())
continue
}
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Session Allocated. Session ID[%d] Call ID[%s]", s.ID, sip.GetCallID())
s.SetSessionMethod(sip)
//session start
s.Start()
} else { //found session
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Session found [%s][%s]", sip.GetCallID(), s.callID)
if sip.Method == icspacketparser.ICS_SIP_METHOD_INVITE {
s.SetCallID(sip.GetCallID())
}
if s.CheckAutomata(&sip) {
s.SetSessionMethod(sip)
} else {
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Not Allowed Method(%d)", s.MethodAutomata)
//TODO : response 400 error
continue
}
//if cancel ACK or bye res, remove the session
if s.MethodAutomata == ICS_SIP_AUTOMATA_CANCEL && sip.Method == icspacketparser.ICS_SIP_METHOD_ACK {
s.Stop()
serr := s.RemoveSession()
if serr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "RemoveSession Error %s", serr.GetMessage())
} else {
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Session Removed")
}
continue
}
}
//post the sip event to session
h := icsevent.NewEventH()
evt, evtErr := h.AllocEvent(sip)
if evtErr != nil {
return evtErr
}
perr := h.PostEvent(s.ID, evt)
//perr := h.PostEvent(int(s.GetSessionID()), evt)
if perr == nil {
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Post SIP event[%d] to Session[%03d]", evt.ID, s.ID)
} else {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to post SIP event[%d] to Session[%03d] - %s",
evt.ID, s.ID, perr.GetError())
}
} else { // no session
switch sip.Method {
case icspacketparser.ICS_SIP_METHOD_OPTIONS:
l.Printf(icslog.LOG_LEVEL_INFO, -1, "%v", sip)
case icspacketparser.ICS_SIP_METHOD_SIP20:
if strings.Contains(strings.ToUpper(sip.Cseq), "OPTIONS") {
//l.Printf(icslog.LOG_LEVEL_INFO, -1, "%v", sip)
} else {
l.Printf(icslog.LOG_LEVEL_INFO, -1, "%v", sip)
}
default:
l.Printf(icslog.LOG_LEVEL_INFO, -1, "%v", sip)
}
}
}
data = nil
}
return nil
}
//bot-command manager
func (sm *SessionManager) RunBotCommandMNG() (icserr *icserror.IcsError) {
l := icslog.GetIcsLog()
conf := icsconf.GetIcsConfig()
//start bot-command listen
commandPort := conf.CommandConfig.Port
commandTransport := conf.CommandConfig.Transport
commandLocalAddrStr := fmt.Sprintf("0.0.0.0:%d", commandPort)
commandLocalAddr := icsnet.NewNetAddrWithIPAddr(commandLocalAddrStr)
var cmdErr *icserror.IcsError
sm.CommNet, cmdErr = icsnet.ListenAndServeTCP(&commandLocalAddr, nil, "\r\n\r\n", BotCommand)
if cmdErr != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, -1, "%s", cmdErr.GetError())
return nil
}
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Listening Bot-Command %s port[%d]", commandTransport, commandPort)
/*
for !svc.GetExit() || !svc.GetStop() {
}
*/
return nil
}
func BotCommand(t *icsnet.IcsTCPNet, bufend string) {
l := icslog.GetIcsLog()
defer t.Close()
for {
ttsHeader, rlen, rerr := t.ReadS(86, bufend)
if rerr != nil {
if rerr.GetError() != io.EOF {
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "[Bot Command] ReadS Error! - %s[%d:%s]",
rerr.GetError(), rlen, len(ttsHeader))
}
break
} else {
l.Printf(icslog.LOG_LEVEL_INFO, -1, "Recved Bot Command(%s)", ttsHeader)
ttscmd := binary.LittleEndian.Uint32(ttsHeader[0:])
ttsrc := binary.LittleEndian.Uint32(ttsHeader[4:])
ttspl := binary.LittleEndian.Uint64(ttsHeader[8:])
agentname := string(ttsHeader[16:])
//remove null terminator
n := bytes.Index([]byte(agentname), []byte{0})
agentName := string([]byte(agentname)[:n])
telno := string(ttsHeader[36:])
m := bytes.Index([]byte(telno), []byte{0})
telNo := string([]byte(telno)[:m])
s := findSessionWithAgentName2(agentName)
if s == nil {
l.Printf(icslog.LOG_LEVEL_ERROR, -1, "Not found session - %s", agentName)
return
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Bot Command(%d) - [%s:%d]", rlen, agentName, ttscmd)
switch ttscmd {
case recorddata.TTS_COMMAND:
l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS command")
//fmt.Println("374LINE", ttscmd, ttsrc, ttspl, agentName)
//recv tts data
tts, rlen, rerr := t.Read(int(ttspl))
if rerr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError())
return
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(tts))
//////////////////////
//RTP start
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP Callback timer %+v", s.RTPSenderCallBackTimer)
s.RTPSenderCallBackTimer.Stop()
s.m.Lock()
s.tts = make([]byte, int(ttspl))
copy(s.tts, tts)
s.m.Unlock()
/*
n := time.Now()
filename := fmt.Sprintf("./%daaabbb%d-2.pcm", s.ID, n.Nanosecond())
ttsfile, ferr := os.OpenFile(filename, os.O_CREATE|os.O_RDWR|os.O_APPEND|os.O_TRUNC|os.O_SYNC, os.FileMode(0644))
if ferr != nil {
fmt.Println(ferr)
os.Exit(1)
}
ttsfile.Write(tts)
ttsfile.Close()
*/
//s.tts = tts
//s.txCnt = 0
//s.callStartTime = time.Now()
s.RTPSenderCallBackTimer.Start()
case recorddata.BYE_COMMAND:
l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Recved BYE command")
//fmt.Println("393LINE", ttscmd, ttsrc, ttspl, agentName)
if int(ttspl) > 0 {
//recv tts data
tts, rlen, rerr := t.Read(int(ttspl))
if rerr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError())
return
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Read T: %v", t)
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(tts))
//////////////////////
//RTP start
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP Callback timer %+v", s.RTPSenderCallBackTimer)
s.RTPSenderCallBackTimer.Stop()
s.m.Lock()
s.tts = make([]byte, int(ttspl))
copy(s.tts, tts)
//s.tts = tts
s.m.Unlock()
//s.txCnt = 0
//s.callStartTime = time.Now()
s.RTPSenderCallBackTimer.Start()
//request bye
sleeptime := int(ttspl) / 16
time.Sleep(time.Millisecond * time.Duration(sleeptime+200))
agentStatus := s.GetAgentStatus()
//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Agent Status: %d", agentStatus)
if agentStatus == STATUS_AGENT_BUSY {
s.RequestBYE(s.InviteSIP)
s.SetAgentStatus(STATUS_AGENT_BYEING)
fmt.Println("AGENT_STATUS : ", s.GetAgentStatus())
}
s.BotStatus = ttscmd
} else {
if s.InviteSIP == nil {
agentStatus := s.GetAgentStatus()
if agentStatus == STATUS_AGENT_BUSY {
s.SetAgentStatus(STATUS_AGENT_ERROR)
}
} else {
s.RequestBYE(s.InviteSIP)
}
}
case recorddata.DTMF_COMMAND:
l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Recved DTMF command")
//fmt.Println("374LINE", ttscmd, ttsrc, ttspl, agentName)
//recv tts data
tts, rlen, rerr := t.Read(int(ttspl))
if rerr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError())
fmt.Println("error : ", rerr.GetError())
return
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(tts))
//////////////////////
//RTP start
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP Callback timer %+v", s.RTPSenderCallBackTimer)
s.RTPSenderCallBackTimer.Stop()
s.m.Lock()
s.tts = make([]byte, int(ttspl))
copy(s.tts, tts)
s.m.Unlock()
s.BotStatus = ttscmd
s.RTPSenderCallBackTimer.Start()
case recorddata.REFER_COMMAND:
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved REFER command %+v", ttscmd)
//fmt.Println("393LINE", ttscmd, ttsrc, ttspl, agentName)
if int(ttspl) > 0 {
//recv tts data
tts, rlen, rerr := t.Read(int(ttspl))
if rerr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError())
return
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(tts))
//////////////////////
//RTP start
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP Callback timer %+v", s.RTPSenderCallBackTimer)
s.RTPSenderCallBackTimer.Stop()
s.m.Lock()
s.tts = make([]byte, int(ttspl))
copy(s.tts, tts)
//s.tts = tts
s.m.Unlock()
//s.txCnt = 0
//s.callStartTime = time.Now()
s.RTPSenderCallBackTimer.Start()
//request bye
sleeptime := int(ttspl) / 16
time.Sleep(time.Millisecond * time.Duration(sleeptime+200))
agentStatus := s.GetAgentStatus()
//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Agent Status: %d", agentStatus)
if agentStatus == STATUS_AGENT_BUSY {
s.RequestRefer(telNo, s.InviteSIP)
s.SetAgentStatus(STATUS_AGENT_BYEING)
fmt.Println("AGENT_STATUS : ", s.GetAgentStatus())
}
s.BotStatus = ttscmd
} else {
if s.InviteSIP == nil {
agentStatus := s.GetAgentStatus()
if agentStatus == STATUS_AGENT_BUSY {
s.SetAgentStatus(STATUS_AGENT_ERROR)
}
} else {
s.RequestRefer(telNo, s.InviteSIP)
}
}
default:
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "485LINE %+v, %+v, %+v, %s", ttscmd, ttsrc, ttspl, agentName)
}
}
fmt.Println("418LINE rlen", rlen, rerr)
}
}

@ -0,0 +1,144 @@
package icssessionmanager
import (
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)
const (
ICS_SIP_AUTOMATA_REGISTER = 32767
//ICS_SIP_AUTOMATA_REGISTER = 2
ICS_SIP_AUTOMATA_INVITE = 32767
ICS_SIP_AUTOMATA_ACK = 32767
ICS_SIP_AUTOMATA_CANCEL = 14336
ICS_SIP_AUTOMATA_BYE = 32767
ICS_SIP_AUTOMATA_NOTIFY = 32767
ICS_SIP_AUTOMATA_OPTIONS = 32767
/*
ICS_SIP_AUTOMATA_INVITE = 11266
ICS_SIP_AUTOMATA_ACK = 32767
ICS_SIP_AUTOMATA_CANCEL = 14336
ICS_SIP_AUTOMATA_BYE = 32767
*/
//ICS_SIP_AUTOMATA_BYE = 0
)
const (
ICS_SIP_JOB_TYPE_REGISTER = 1 << iota
ICS_SIP_JOB_TYPE_INVITE
ICS_SIP_JOB_TYPE_PUBLISH
ICS_SIP_JOB_TYPE_OPTIONS
ICS_SIP_JOB_TYPE_INFO
ICS_SIP_JOB_TYPE_UPDATE
ICS_SIP_JOB_TYPE_REFER
ICS_SIP_JOB_TYPE_SUBSCRIBE
ICS_SIP_JOB_TYPE_MESSAGE
ICS_SIP_JOB_TYPE_NOTIFY
ICS_SIP_JOB_TYPE_PRACK
ICS_SIP_JOB_TYPE_ACK
ICS_SIP_JOB_TYPE_BYE
ICS_SIP_JOB_TYPE_CANCEL
)
func SessionAvailableSipMethod(sip *icspacketparser.SIP) bool {
if sip.Method == icspacketparser.ICS_SIP_METHOD_INVITE || sip.Method == icspacketparser.ICS_SIP_METHOD_CANCEL || sip.Method == icspacketparser.ICS_SIP_METHOD_BYE || sip.Method == icspacketparser.ICS_SIP_METHOD_ACK || sip.Method == icspacketparser.ICS_SIP_METHOD_NOTIFY {
return true
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 {
if strings.Contains(sip.Cseq, " INVITE") || strings.Contains(sip.Cseq, " CANCEL") || strings.Contains(sip.Cseq, " BYE") || strings.Contains(sip.Cseq, " ACK") || strings.Contains(sip.Cseq, " REGISTER") || strings.Contains(sip.Cseq, " OPTIONS") {
return true
/*
if sip.ResType == "183" || sip.ResType == "200" {
return true
}
*/
}
}
return false
}
func (s *IcsSession) CheckAutomataWithType(methodType int) bool {
return (s.MethodAutomata & methodType) == methodType
}
func (s *IcsSession) CheckAutomata(sip *icspacketparser.SIP) bool {
jobType := GetJobType(sip)
return (s.MethodAutomata & jobType) == jobType
/*
// fmt.Println("^^^^^", "s.MethodAutomata,jobType,sip.Method", s.MethodAutomata, jobType, sip.Method)
if (s.MethodAutomata&jobType) == jobType || jobType == ICS_SIP_JOB_TYPE_BYE {
// fmt.Println("^^^^^", "automata find ok")
return true
}
// fmt.Println("^^^^^", "not allow automata sip.Cseq", sip.Cseq)
return false
*/
}
func GetJobType(sip *icspacketparser.SIP) int {
if sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 {
if strings.Contains(sip.Cseq, " INVITE") {
return ICS_SIP_JOB_TYPE_INVITE
} else if strings.Contains(sip.Cseq, " ACK") {
return ICS_SIP_JOB_TYPE_ACK
} else if strings.Contains(sip.Cseq, " BYE") {
return ICS_SIP_JOB_TYPE_BYE
} else if strings.Contains(sip.Cseq, " REGISTER") {
return ICS_SIP_JOB_TYPE_REGISTER
} else if strings.Contains(sip.Cseq, " CANCEL") {
return ICS_SIP_JOB_TYPE_CANCEL
} else if strings.Contains(sip.Cseq, " OPTIONS") {
return ICS_SIP_JOB_TYPE_OPTIONS
}
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_REGISTER {
return ICS_SIP_JOB_TYPE_REGISTER
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_INVITE {
return ICS_SIP_JOB_TYPE_INVITE
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_CANCEL {
return ICS_SIP_JOB_TYPE_CANCEL
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_BYE {
return ICS_SIP_JOB_TYPE_BYE
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_ACK {
return ICS_SIP_JOB_TYPE_ACK
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_NOTIFY {
return ICS_SIP_JOB_TYPE_NOTIFY
}
return -1
}
func (s *IcsSession) SetSessionMethodWithType(methodType int) {
s.MethodAutomata = methodType
}
func (s *IcsSession) SetSessionMethod(sip icspacketparser.SIP) {
if sip.Method == icspacketparser.ICS_SIP_METHOD_SIP20 {
if strings.Contains(sip.Cseq, " REGISTER") {
s.MethodAutomata = ICS_SIP_AUTOMATA_REGISTER
//fmt.Println(">>>>>>>>>>", s.MethodAutomata, ICS_SIP_AUTOMATA_REGISTER)
} else if strings.Contains(sip.Cseq, " INVITE") {
s.MethodAutomata = ICS_SIP_AUTOMATA_INVITE
} else if strings.Contains(sip.Cseq, " CANCEL") {
s.MethodAutomata = ICS_SIP_AUTOMATA_CANCEL
} else if strings.Contains(sip.Cseq, " BYE") {
s.MethodAutomata = ICS_SIP_AUTOMATA_BYE
} else if strings.Contains(sip.Cseq, " ACK") {
s.MethodAutomata = ICS_SIP_AUTOMATA_ACK
} else if strings.Contains(sip.Cseq, " OPTIONS") {
s.MethodAutomata = ICS_SIP_AUTOMATA_OPTIONS
}
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_REGISTER {
s.MethodAutomata = ICS_SIP_AUTOMATA_REGISTER
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_INVITE {
s.MethodAutomata = ICS_SIP_AUTOMATA_INVITE
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_CANCEL {
s.MethodAutomata = ICS_SIP_AUTOMATA_CANCEL
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_BYE {
s.MethodAutomata = ICS_SIP_AUTOMATA_BYE
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_ACK {
s.MethodAutomata = ICS_SIP_AUTOMATA_ACK
} else if sip.Method == icspacketparser.ICS_SIP_METHOD_NOTIFY {
s.MethodAutomata = ICS_SIP_AUTOMATA_NOTIFY
}
}

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

@ -0,0 +1,18 @@
package icssessionmanager
const (
//register status
STATUS_REGISTER_NOT_READY = 1 << iota
STATUS_REGISTER_READY
STATUS_REGISTER_REQUEST
STATUS_REGISTER_REGISTERED
STATUS_REGISTER_EXPIRED
//phone-agent status
STATUS_AGENT_NOT_READY
STATUS_AGENT_READY
STATUS_AGENT_CALLING
STATUS_AGENT_CANCELING
STATUS_AGENT_BUSY
STATUS_AGENT_BYEING
STATUS_AGENT_ERROR
)

@ -0,0 +1,59 @@
<?xml version="1.0"?>
<ICSSIP version="1.0.0.0">
<INFO>
<CHANNELID>00001</CHANNELID>
<SERVERID>00</SERVERID>
<SERVERIP>192.168.0.21</SERVERIP>
</INFO>
<CALLEVENT value="false" production="ICOMSYS" version="1.0.0.1"/>
<SIP value="true" transport="udp" port="5090"/>
<AGENT name="9012" value="false">
<!-- if register value is false, it works to TRUNK mode-->
<REGISTER value="false" proxy="192.168.0.222:5090" transport="udp" expire="3600" username="9012"/>
<MEDIA m="aud" port="21000" format="PCMU PCMA"/>
</AGENT>
<AGENT name="9013" value="true">
<REGISTER value="true" proxy="192.168.0.222:5090" transport="udp" expire="3600" username="9013"/>
<MEDIA m="aud" port="21002" format="PCMU PCMA"/>
</AGENT>
<AGENT name="9014" value="false">
<REGISTER value="false" proxy="192.168.0.222:5090" transport="udp" expire="3600" username="9014"/>
<MEDIA m="aud" port="21004" format="PCMU PCMA"/>
</AGENT>
<AGENT name="9015" value="false">
<REGISTER value="false" proxy="192.168.0.222:5090" transport="udp" expire="3600" username="9015"/>
<MEDIA m="aud" port="21006" format="PCMU PCMA"/>
</AGENT>
<AGENT name="9016" value="false">
<REGISTER value="false" proxy="192.168.0.222:5090" transport="udp" expire="3600" username="9016"/>
<MEDIA m="aud" port="21008" format="PCMU PCMA"/>
</AGENT>
<AGENT name="9017" value="false">
<REGISTER value="false" proxy="192.168.0.222:5090" transport="udp" expire="3600" username="9017"/>
<MEDIA m="aud" port="21010" format="PCMU PCMA"/>
</AGENT>
<AGENT name="9018" value="false">
<REGISTER value="false" proxy="192.168.0.222:5090" transport="udp" expire="3600" username="9018"/>
<MEDIA m="aud" port="21012" format="PCMU PCMA"/>
</AGENT>
<AGENT name="9019" value="false">
<REGISTER value="false" proxy="192.168.0.222:5090" transport="udp" expire="3600" username="9019"/>
<MEDIA m="aud" port="21014" format="PCMU PCMA"/>
</AGENT>
<CAPTURE>
<DEVICE>enp2s0</DEVICE>
<FILTER>(udp[1] &amp; 1 != 1 &amp;&amp; udp[3] &amp; 1 != 1 &amp;&amp; udp[8] &amp; 0x80 == 0x80 &amp;&amp; length &lt; 256) or (port 5060) or (portrange 6000-6127)</FILTER>
</CAPTURE>
<VOICEAGENT>
<AGENT callsignalport="57777" voiceport="57778">192.168.0.21</AGENT>
<SERVER port="7777" baseport="7778" range="128">192.168.0.21</SERVER>
</VOICEAGENT>
<PBX>
<IP>192.168.0.222</IP>
<PORT>5090</PORT>
</PBX>
</ICSIP>

@ -0,0 +1,215 @@
package icssvc
import (
"fmt"
"os"
"sync"
"time"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/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()
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)
}
if d1 != d2 || y1 != y2 || m1 != m2 {
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/icsvg.log-%d%02d%02d", s.log.Path, y2, m2, d2)
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
}

@ -0,0 +1,4 @@
#!/usr/bin/sh
HOME=$ICSVG_ROOT
`cat $HOME/voicegateway.pid | xargs kill`
echo "VoiceGateway Stoped..."

@ -0,0 +1,269 @@
package icsutil
import (
"fmt"
"io/ioutil"
"os"
"os/signal"
"strings"
"syscall"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/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], "ICSVG_ROOT") == 0 {
homeDir = s[1]
//service.SetHomeDir(s[1])
isStop = true
break
}
}
if isStop {
pidFilename := fmt.Sprintf("%s/voicegateway.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], "ICSVG_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
}
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], "ICSVG_ROOT") == 0 {
homeDir = s[1]
//service.SetHomeDir(s[1])
isStop = true
break
}
}
if isStop {
pidFilename := fmt.Sprintf("%s/voicegateway.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], "ICSVG_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
}

@ -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
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

@ -0,0 +1,25 @@
package main
import (
"flag"
"fmt"
"strconv"
"syscall"
)
func main() {
flag.Parse()
if flag.NArg() < 1 {
fmt.Println("사용법: insert pid")
return
}
var pid int
pid, _ = strconv.Atoi(flag.Arg(0))
//syscall.Kill(syscall.Getpid(), syscall.SIGINT)
syscall.Kill(pid, syscall.SIGINT)
fmt.Println("kill pid")
}

Binary file not shown.

@ -0,0 +1,68 @@
package main
import (
"fmt"
"os"
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/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], "ICSVG_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/icsvg.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)
}

@ -0,0 +1,27 @@
package recorddata
const (
TTS_COMMAND = iota
REFER_COMMAND
BYE_COMMAND
BARGEIN_COMMAND
DTMF_COMMAND
)
type BotCommandData struct {
Token string
CallID string
Method string
TelNO string
STTResult string
}
func NewBotCommandData(callID string, telNo string) *BotCommandData {
b := BotCommandData{CallID: callID, TelNO: telNo}
return &b
}
func (b *BotCommandData) SetData() {
}

@ -0,0 +1,6 @@
package recorddata
const (
MAX_CALLSIGNAL_PACKET_LEN = 81
//MAX_CALLSIGNAL_PACKET_LEN = 61
)

@ -0,0 +1,84 @@
package readcallsignal
import (
"encoding/binary"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/recorddata"
)
type CallSignal struct {
ChannelID string
ServerID int
AgentID string
Station string
//Station int
CreateTime int64
EventType string
StartTime int64
EndTime int64
InOut string
CustID string
}
type CallSignalP struct {
CallSignal [recorddata.MAX_CALLSIGNAL_PACKET_LEN]byte
}
//call signal protocol offset. ex)buffer[id:len]
const (
CHANNELID = 0 //byte array 13
CHANNELID_LEN = 13 //byte array 13
SERVERID = CHANNELID + 13 //short 2
SERVERID_LEN = SERVERID + 2 //short 2
AGENTID = SERVERID + 2 //byte array 16
AGENTID_LEN = AGENTID + 16 //byte array 16
STATION = AGENTID + 16 //int 4
STATION_LEN = STATION + 4 //int 4
CREATETIME = STATION + 4 //long 8
CREATETIME_LEN = CREATETIME + 8 //long 8
EVENTTYPE = CREATETIME + 8 //byte 1
EVENTTYPE_LEN = EVENTTYPE + 1 //byte 1
STARTTIME = EVENTTYPE + 1 //long 8
STARTTIME_LEN = STARTTIME + 8 //long 8
ENDTIME = STARTTIME + 8 //long 8
ENDTIME_LEN = ENDTIME + 8 //long 8
INOUT = ENDTIME + 8 //byte 1
INOUT_LEN = INOUT + 1 //byte 1
CUSTID = INOUT + 1 //byte 20
CUSTID_LEN = CUSTID + 20 //byte 20
)
func NewCallSignal(data []byte) *CallSignal {
if len(data) > recorddata.MAX_CALLSIGNAL_PACKET_LEN {
return nil
}
cs := CallSignal{}
cs.parse(data)
//fmt.Printf("%+v\n", cs)
return &cs
}
func (cs *CallSignal) parse(data []byte) {
defer func() {
if err := recover(); err != nil {
l := icslog.GetIcsLog()
l.Print(icslog.LOG_LEVEL_WARN, -1, icserror.ICSERRRECORDDATAParsing.GetMessage())
}
}()
cs.ChannelID = string(data[CHANNELID:CHANNELID_LEN])
cs.ServerID = int(binary.LittleEndian.Uint16(data[SERVERID:SERVERID_LEN]))
cs.AgentID = string(data[AGENTID:AGENTID_LEN])
cs.Station = string(data[STATION:STATION_LEN])
//cs.Station = int(binary.LittleEndian.Uint32(data[STATION:STATION_LEN]))
cs.CreateTime = int64(binary.LittleEndian.Uint64(data[CREATETIME:CREATETIME_LEN]))
cs.EventType = string(data[EVENTTYPE:EVENTTYPE_LEN][0])
cs.StartTime = int64(binary.LittleEndian.Uint64(data[STARTTIME:STARTTIME_LEN]))
cs.EndTime = int64(binary.LittleEndian.Uint64(data[ENDTIME:ENDTIME_LEN]))
cs.InOut = string(data[INOUT:INOUT_LEN][0])
cs.CustID = string(data[CUSTID:CUSTID_LEN])
}

@ -0,0 +1,205 @@
package recorddata
import (
"encoding/binary"
"fmt"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)
type VoiceData struct {
stream []byte
}
type VoiceDataHDR struct {
ServerID int
CreateTime int64
Station int
Seq int
Type byte
Codec string
Payload []byte
}
const (
VOICE_DATA_LEN = 340
vcSERVERID_POS = 0
vcSERVERID_LEN = 2
vcCREATETIME_POS = vcSERVERID_POS + 2
vcCREATETIME_LEN = vcCREATETIME_POS + 8
vcSTATION_POS = vcCREATETIME_POS + 8
vcSTATION_LEN = vcSTATION_POS + 4
vcSEQUENCE_POS = vcSTATION_POS + 4
vcSEQUENCE_LEN = vcSEQUENCE_POS + 4
vcTYPE_POS = vcSEQUENCE_POS + 4
vcTYPE_LEN = vcTYPE_POS + 1
vcCODEC_POS = vcTYPE_POS + 1
vcCODEC_LEN = vcCODEC_POS + 1
vcPAYLOAD_POS = vcCODEC_POS + 1
vcPAYLOAD_LEN = vcPAYLOAD_POS + 320
)
func NewVoiceData() *VoiceData {
v := &VoiceData{
stream: make([]byte, VOICE_DATA_LEN),
}
return v
}
func NewVoiceDataHDR(voicedata []byte) *VoiceDataHDR {
hdr := VoiceDataHDR{}
hdr.parse(voicedata)
return &hdr
}
func (hdr *VoiceDataHDR) parse(data []byte) {
defer func() {
if err := recover(); err != nil {
l := icslog.GetIcsLog()
l.Print(icslog.LOG_LEVEL_WARN, -1, icserror.ICSERRRECORDDATAParsing.GetMessage())
}
}()
hdr.ServerID = int(binary.LittleEndian.Uint16(data[vcSEQUENCE_POS:vcSEQUENCE_LEN]))
hdr.CreateTime = int64(binary.LittleEndian.Uint64(data[vcCREATETIME_POS:vcCREATETIME_LEN]))
hdr.Station = int(binary.LittleEndian.Uint32(data[vcSTATION_POS:vcSTATION_LEN]))
hdr.Seq = int(binary.LittleEndian.Uint32(data[vcSEQUENCE_POS:vcSEQUENCE_LEN]))
hdr.Type = data[vcTYPE_POS:vcTYPE_LEN][0]
hdr.Codec = fmt.Sprintf("%d", data[vcCODEC_POS:vcCODEC_LEN])
hdr.Payload = data[vcPAYLOAD_POS:vcPAYLOAD_LEN]
}
func (v *VoiceData) SetData(serverID int, station string, sequence int32, timestamp int64, calltype string, codec icspacketparser.PayloadType, payload []byte) {
v.setServerID(serverID)
v.setCreateTime(timestamp)
v.setStation(station)
v.setSequence(sequence)
v.setType(calltype)
v.setCodec2(codec)
//v.setCodec(codec)
v.setPayload(payload)
}
func (v VoiceData) GetData() []byte {
return v.stream
}
func (v *VoiceData) setServerID(serverID int) {
id := fmt.Sprintf("%d", serverID)
tmp := []byte(id)
copy(v.stream[vcSERVERID_POS:vcSERVERID_LEN], tmp)
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setServerID> %d-%v", len(v.stream[vcSERVERID_POS:vcSERVERID_LEN]), v)
}
func (v *VoiceData) setCreateTime(createtime int64) {
tmp := make([]byte, 8)
binary.LittleEndian.PutUint64(tmp, uint64(createtime))
copy(v.stream[vcCREATETIME_POS:vcCREATETIME_LEN], tmp)
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setCreateTime> %d-%v", len(v.stream[vcCREATETIME_POS:vcCREATETIME_LEN]), v)
}
func (v *VoiceData) setStation(station string) {
//tmp := make([]byte, 4)
//binary.LittleEndian.PutUint32(tmp, uint32(station))
copy(v.stream[vcSTATION_POS:vcSTATION_LEN], []byte(station))
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setStation> %d-%v", len(v.stream[vcSTATION_POS:vcSTATION_LEN]), v)
}
func (v *VoiceData) setSequence(sequence int32) {
tmp := make([]byte, 4)
binary.LittleEndian.PutUint32(tmp, uint32(sequence))
copy(v.stream[vcSEQUENCE_POS:vcSEQUENCE_LEN], tmp)
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setSequence> %d-%v", len(v.stream[vcSEQUENCE_POS:vcSEQUENCE_LEN]), v)
}
func (v *VoiceData) setType(calltype string) {
tmp := make([]byte, 4)
if calltype == "0" {
binary.LittleEndian.PutUint32(tmp, uint32(0))
} else {
binary.LittleEndian.PutUint32(tmp, uint32(1))
}
copy(v.stream[vcTYPE_POS:vcTYPE_LEN], tmp)
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setType> %d-%v", len(v.stream[vcTYPE_POS:vcTYPE_LEN]), v)
}
func (v *VoiceData) setCodec(codec string) {
tmp := make([]byte, 4)
if codec == "0" {
binary.LittleEndian.PutUint32(tmp, uint32(0))
} else if codec == "8" {
binary.LittleEndian.PutUint32(tmp, uint32(8))
} else if codec == "18" {
binary.LittleEndian.PutUint32(tmp, uint32(18))
}
copy(v.stream[vcCODEC_POS:vcCODEC_LEN], tmp)
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setCodec> %d-%v", len(v.stream[vcCODEC_POS:vcCODEC_LEN]), v)
}
func (v *VoiceData) setCodec2(codec icspacketparser.PayloadType) {
tmp := make([]byte, 4)
if codec == 0 {
binary.LittleEndian.PutUint32(tmp, uint32(0))
} else if codec == 8 {
binary.LittleEndian.PutUint32(tmp, uint32(8))
} else if codec == 18 {
binary.LittleEndian.PutUint32(tmp, uint32(18))
}
copy(v.stream[vcCODEC_POS:vcCODEC_LEN], tmp)
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setCodec> %d-%v", len(v.stream[vcCODEC_POS:vcCODEC_LEN]), v)
}
func (v *VoiceData) setPayload(payload []byte) {
copy(v.stream[vcPAYLOAD_POS:vcPAYLOAD_LEN], payload)
//l := icslog.GetIcsLog()
//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setPayload> %d-%v", len(v.stream[vcPAYLOAD_POS:vcPAYLOAD_LEN]), v)
}
func (v VoiceData) GetServerID() []byte {
return v.stream[vcSERVERID_POS:vcSERVERID_LEN]
}
func (v VoiceData) GetCreateTime() []byte {
return v.stream[vcCREATETIME_POS:vcCREATETIME_LEN]
}
func (v VoiceData) GetStation() []byte {
return v.stream[vcSTATION_POS:vcSTATION_LEN]
}
func (v VoiceData) GetSequence() []byte {
return v.stream[vcSEQUENCE_POS:vcSEQUENCE_LEN]
}
func (v VoiceData) GetType() []byte {
return v.stream[vcTYPE_POS:vcTYPE_LEN]
}
func (v VoiceData) GetCodec() []byte {
return v.stream[vcCODEC_POS:vcCODEC_LEN]
}
func (v VoiceData) GetPayload() []byte {
return v.stream[vcPAYLOAD_POS:vcPAYLOAD_LEN]
}

@ -0,0 +1,190 @@
package writecallsignal
import (
"encoding/binary"
"fmt"
"gitlab.com/ics_cinnamon/voicegateway/recorddata"
)
type CallSignalData struct {
stream []byte
}
const (
//CALLSIGNAL_DATA_LEN = 61
CHANNELID_POS = 0 //13
CHANNELID_LEN = 13
SERVERID_POS = CHANNELID_POS + 13 //2
SERVERID_LEN = SERVERID_POS + 2
AGENTID_POS = SERVERID_POS + 2 //16
AGENTID_LEN = AGENTID_POS + 16
STATION_POS = AGENTID_POS + 16 //4
STATION_LEN = STATION_POS + 4
CREATETIME_POS = STATION_POS + 4 //8
CREATETIME_LEN = CREATETIME_POS + 8
EVENTTYPE_POS = CREATETIME_POS + 8 //1
EVENTTYPE_LEN = EVENTTYPE_POS + 1
STARTTIME_POS = EVENTTYPE_POS + 1 //8
STARTTIME_LEN = STARTTIME_POS + 8
ENDTIME_POS = STARTTIME_POS + 8 //8
ENDTIME_LEN = ENDTIME_POS + 8
INOUT_POS = ENDTIME_POS + 8 //1
INOUT_LEN = INOUT_POS + 1
CUSTID_POS = INOUT_POS + 1 //1
CUSTID_LEN = CUSTID_POS + 20
)
func NewCallSignalData() *CallSignalData {
c := &CallSignalData{
stream: make([]byte, recorddata.MAX_CALLSIGNAL_PACKET_LEN),
}
return c
}
func (c *CallSignalData) SetData(chanID string, serverID int, station string, custID string, startTS int64, endTS int64, event, inout string) {
c.setChannelID(chanID)
c.setServerID(serverID)
agentid := fmt.Sprintf("agent%s", station)
c.setAgentID(agentid)
c.setStation(station)
c.setCreateTime(startTS)
c.setEventType(event)
c.setStartTime(startTS)
c.setEndTime(endTS)
c.setInOut(inout)
c.setCustID(custID)
}
func (c CallSignalData) GetData() []byte {
return c.stream
}
func (c *CallSignalData) setChannelID(channelID string) {
tmp := []byte(channelID)
copy(c.stream[CHANNELID_POS:CHANNELID_LEN], tmp)
}
func (c CallSignalData) GetChannelID() []byte {
return c.stream[CHANNELID_POS:CHANNELID_LEN]
}
func (c *CallSignalData) setServerID(serverID int) {
id := fmt.Sprintf("%d", serverID)
tmp := []byte(id)
copy(c.stream[SERVERID_POS:SERVERID_LEN], tmp)
}
func (c CallSignalData) GetServerID() []byte {
return c.stream[SERVERID_POS:SERVERID_LEN]
}
func (c *CallSignalData) setAgentID(agentID string) {
tmp := []byte(agentID)
copy(c.stream[AGENTID_POS:AGENTID_LEN], tmp)
}
func (c CallSignalData) GetAgentID() []byte {
return c.stream[AGENTID_POS:AGENTID_LEN]
}
func (c *CallSignalData) setStation(station string) {
//func (c *CallSignalData) setStation(station string) {
//tmp := make([]byte, 4)
//binary.LittleEndian.PutUint32(tmp, uint32(station))
copy(c.stream[STATION_POS:STATION_LEN], []byte(station))
}
func (c CallSignalData) GetStation() []byte {
return c.stream[STATION_POS:STATION_LEN]
}
func (c *CallSignalData) setCreateTime(createtime int64) {
tmp := make([]byte, 8)
binary.LittleEndian.PutUint64(tmp, uint64(createtime))
copy(c.stream[CREATETIME_POS:CREATETIME_LEN], tmp)
}
func (c CallSignalData) GetCreateTime() []byte {
return c.stream[CREATETIME_POS:CREATETIME_LEN]
}
func (c *CallSignalData) setEventType(eventtype string) {
tmp := []byte(eventtype)
copy(c.stream[EVENTTYPE_POS:EVENTTYPE_LEN], tmp)
}
func (c CallSignalData) GetEventType() []byte {
return c.stream[EVENTTYPE_POS:EVENTTYPE_LEN]
}
func (c *CallSignalData) setStartTime(starttime int64) {
tmp := make([]byte, 8)
binary.LittleEndian.PutUint64(tmp, uint64(starttime))
copy(c.stream[STARTTIME_POS:STARTTIME_LEN], tmp)
}
func (c CallSignalData) GetStartTime() []byte {
return c.stream[STARTTIME_POS:STARTTIME_LEN]
}
func (c *CallSignalData) setEndTime(endtime int64) {
tmp := make([]byte, 8)
binary.LittleEndian.PutUint64(tmp, uint64(endtime))
copy(c.stream[ENDTIME_POS:ENDTIME_LEN], tmp)
}
func (c CallSignalData) GetEndTime() []byte {
return c.stream[ENDTIME_POS:ENDTIME_POS]
}
func (c *CallSignalData) setInOut(inout string) {
var tmp []byte = make([]byte, 1)
switch inout {
case "10":
//tmp = []byte("-1")
u := -1
tmp[0] = byte(u)
case "11":
//tmp = []byte("-2")
u := -2
tmp[0] = byte(u)
case "12":
//tmp = []byte("-3")
u := -3
tmp[0] = byte(u)
case "13":
//tmp = []byte("-4")
u := -4
tmp[0] = byte(u)
case "14":
//tmp = []byte("-5")
u := -5
tmp[0] = byte(u)
case "15":
//tmp = []byte("-6")
u := -6
tmp[0] = byte(u)
default:
tmp = []byte(inout)
}
copy(c.stream[INOUT_POS:INOUT_LEN], tmp)
tmp = nil
}
func (c CallSignalData) GetInOut() []byte {
return c.stream[INOUT_POS:INOUT_LEN]
}
func (c *CallSignalData) setCustID(custID string) {
//fmt.Println(custID)
tmp := []byte(custID)
//fmt.Println(custID, tmp)
copy(c.stream[CUSTID_POS:CUSTID_LEN], tmp)
}
func (c CallSignalData) GetCustID() []byte {
return c.stream[CUSTID_POS:CUSTID_LEN]
}

Binary file not shown.

@ -0,0 +1,4 @@
INVITE
ACK
TIME: 10
BYE

@ -0,0 +1,76 @@
/*
rfc 3550
*/
package icspacketgen
import (
"encoding/binary"
"math/rand"
"time"
)
type RTPDataHeader struct {
PayloadType int
Sequence int
Timestamp int
SSRC int
}
type RTPHeader struct {
part uint16 //v,p,x,m,pt
seq uint16
timestamp uint32
ssrc uint32
}
const RTPHEADER_LEN = 12
func NewRTP() *RTPDataHeader {
r := &RTPDataHeader{}
return r
}
func (r *RTPDataHeader) MakeRTPData(pt uint8, seq *uint16, timestamp *uint32, ssrc uint32, payload []byte) []byte {
payloadSize := len(payload)
rtp := make([]byte, RTPHEADER_LEN+payloadSize)
//version
rtp[0] = uint8(2) << 6
//padding
rtp[0] |= uint8(1) << 5
//payload type
rtp[1] = uint8(pt)
//sequence number
binary.BigEndian.PutUint16(rtp[2:4], *seq)
//timestamp
binary.BigEndian.PutUint32(rtp[4:8], *timestamp)
//ssrc
binary.BigEndian.PutUint32(rtp[8:12], ssrc)
//payload
copy(rtp[12:], payload)
//fmt.Println("RTP>>>", rtp)
incSeq(seq)
incTimeStamp(timestamp)
return rtp
}
func incTimeStamp(ts *uint32) {
*ts += uint32(160)
}
func incSeq(seq *uint16) {
*seq++
}
func GenSSRC() uint32 {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
ret := r.Uint32()
//fmt.Println(">>>", ret)
return ret
}

@ -0,0 +1,56 @@
package main
// #cgo CFLAGS: -v
import (
"fmt"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
"gitlab.com/ics_cinnamon/voicegateway/sim/simapp"
"gitlab.com/ics_cinnamon/voicegateway/sim/siptemplate"
)
func main() {
service := icssvc.NewService()
fmt.Println("Hello VoiceGateway! Here We Go~\n")
conf, confErr := icsconf.OpenSimConfig("/home/icsvg/sim/simvg.xml", "/home/icsvg/sim/")
if confErr != nil {
confErr.PrintWithCaller(0)
return
}
_, sipScenErr := icsconf.OpenSimScenarioConfig("/home/icsvg/sim/scen.xml", "/home/icsvg/sim/")
if sipScenErr != nil {
sipScenErr.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.Print()
}
service.SetIcsLog(icsLog)
go service.LogWatcher()
icsLog.Print(icslog.LOG_LEVEL_INFO, -1, "Hello VoiceGateway! Here We Go~\n")
confmsg := conf.ShowConfig()
icsLog.Print(icslog.LOG_LEVEL_INFO, -1, confmsg)
siptemplate.Init()
//fmt.Println(">>>>", t.String(0))
//sp := simphone.NewSimPhone()
//fmt.Println("call id", sp.CallID)
app := simapp.Init()
app.Execute()
}

@ -0,0 +1,82 @@
package simapp
import (
"fmt"
"runtime"
"sync"
"time"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
"gitlab.com/ics_cinnamon/voicegateway/sim/simphone"
)
type SimExec struct {
service *icssvc.IcsService
}
func Init() (e *SimExec) {
e = &SimExec{}
e.service = icssvc.GetServiceStatus()
return e
}
func (exe SimExec) Execute() *icserror.IcsError {
l := icslog.GetIcsLog()
simconf := icsconf.GetSimConfig()
loop := simconf.Repeat
l.Printf(icslog.LOG_LEVEL_INFO, -1, "go routine number %d", runtime.NumGoroutine())
// chNum := simconf.Channels
///////////////////////
//create sip phone goroutine
wg := new(sync.WaitGroup)
for iter := 0; iter < loop; iter++ {
l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "Create [%d]SimPhone#####################################", iter)
//wg.Add(1)
pF := func(id int) {
l.Printf(icslog.LOG_LEVEL_DEBUG2, id, "Sim Phone[%d] Start#####################################", id)
// for i := 0; i < loop; i++ {
// fmt.Println(iter, loop)
// l.Printf(icslog.LOG_LEVEL_INFO, id, "go routine number %d", runtime.NumGoroutine())
// sp := simphone.NewSimPhone(id)
// err := sp.Run()
// if err != nil {
// l.Printf(icslog.LOG_LEVEL_FATAL, id, "SIM Phone Failed-%s", err.GetError())
// wg.Done()
// return
// }
// l.Printf(icslog.LOG_LEVEL_INFO, id, "[%dth] DONE[%d]#####################################", i, loop)
// l.Printf(icslog.LOG_LEVEL_INFO, id, "go routine number %d", runtime.NumGoroutine())
// }
fmt.Println(iter, loop)
l.Printf(icslog.LOG_LEVEL_INFO, id, "go routine number %d", runtime.NumGoroutine())
sp := simphone.NewSimPhone(id)
err := sp.Run()
if err != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, id, "SIM Phone Failed-%s", err.GetError())
wg.Done()
return
}
l.Printf(icslog.LOG_LEVEL_INFO, id, "[%dth] DONE[%d]#####################################", loop)
l.Printf(icslog.LOG_LEVEL_INFO, id, "go routine number %d", runtime.NumGoroutine())
l.Printf(icslog.LOG_LEVEL_DEBUG2, id, "Sim Phone[%d] Completed#####################################", id)
wg.Done()
}
//}(iter)
wg.Add(1)
go pF(iter)
time.Sleep(time.Millisecond)
}
wg.Wait()
l.Printf(icslog.LOG_LEVEL_INFO, -1, "go routine number %d", runtime.NumGoroutine())
l.Print(icslog.LOG_LEVEL_INFO, -1, "Bye VoiceCapture~")
return nil
}

@ -0,0 +1,376 @@
package simphone
import (
"bytes"
"fmt"
"os"
"strings"
"sync"
"time"
"github.com/google/uuid"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icsmediaconv"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
"gitlab.com/ics_cinnamon/voicegateway/sim/icspacketgen"
"gitlab.com/ics_cinnamon/voicegateway/sim/simprocnew"
)
type SimPhone struct {
isCaller bool
ID int
CallID string
PayloadType int
SSRC uint32
Seq uint16
Timestamp uint32
TSIPPort int
SIPPort int
RTPTxPort int
RTPCBTxPort int
TRTPTxPort int
lsaddr *icsnet.IcsNetAddr //local sip addr
laddr *icsnet.IcsNetAddr //local rtp addr
rsaddr *icsnet.IcsNetAddr //remote sip addr
raddr *icsnet.IcsNetAddr //remote rtp addr
localRTPUDP *icsnet.IcsUDPNet
sentTime int
sendRTPStatus bool
expTime time.Time
mediaStart int
wgMedia sync.WaitGroup
rtptimer *time.Timer
}
func NewSimPhone(id int) *SimPhone {
s := &SimPhone{}
simconf := icsconf.GetSimConfig()
s.ID = id
if strings.Compare("YES", strings.ToUpper(simconf.IsCaller)) == 0 {
s.CallID = uuid.New().String()
s.isCaller = true
//fmt.Println("Call ID -", s.CallID)
}
s.SSRC = icspacketgen.GenSSRC()
s.Seq = 1
s.PayloadType = icsmediaconv.ICS_PT_ALAW
s.SIPPort = simconf.SimPhoneConfig.SIPPort
s.TSIPPort = simconf.TargetPhoneConfig.TSIPPort
s.TRTPTxPort = simconf.TargetPhoneConfig.TRTPPort + (s.ID * 2) //targetRTPTxPort
s.RTPTxPort = simconf.SimPhoneConfig.RTPPort + (s.ID * 2) //localRTPTxPort
la1 := icsnet.NewNetAddrWithIPPort(simconf.SimPhoneConfig.MYIP, s.SIPPort)
s.lsaddr = &la1
la2 := icsnet.NewNetAddrWithIPPort(simconf.SimPhoneConfig.MYIP, s.RTPTxPort)
s.laddr = &la2
s.sentTime = 0
s.sendRTPStatus = false
s.wgMedia = sync.WaitGroup{}
return s
}
func (s *SimPhone) SetRemoteAddr(saddr *icsnet.IcsNetAddr, addr *icsnet.IcsNetAddr) { //sip addr, rtp addr
s.rsaddr = saddr
s.raddr = addr
}
func (s *SimPhone) Run() *icserror.IcsError {
svc := icssvc.GetServiceStatus()
l := icslog.GetIcsLog()
l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Phone[%d] Started! SIP addr: %v, RTP addr: %v\n",
s.ID, s.lsaddr, s.laddr)
l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "%s\n", s.String())
simconf := icsconf.GetSimConfig()
//make rtp event timer
s.rtptimer = time.NewTimer(time.Millisecond)
rtpReadTimer := time.NewTicker(time.Second)
wgRTPListen := sync.WaitGroup{}
//create rtp liesten goroutine
s.localRTPUDP = icsnet.NewUDP(s.laddr, nil)
lerr := s.localRTPUDP.Listen()
if lerr == nil {
wgRTPListen.Add(1)
go func() {
fmt.Println("############### start rtp", s.laddr)
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Start RTP Listen[%v]\n", s.laddr)
totalRlen := 0
for s.mediaStart != 2 || !svc.GetExit() || !svc.GetStop() {
_, _, rlen, rtperr := s.localRTPUDP.ReadRTP()
if rtperr == nil {
s.expTime = time.Now()
totalRlen += rlen
} else {
fmt.Printf("\nTotal Recved RTP Length[%d]\n", totalRlen)
fmt.Println("##### id : ", s.ID)
break
}
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Stoped[%d] RTP Listen[%v] Total Recved RTP length %d\n", s.mediaStart, s.laddr, totalRlen)
wgRTPListen.Done()
}()
} else {
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to listen RTP[%v] - %v\n", s.laddr, lerr)
return nil
}
///////////////////////////
//CALLER SIDE
l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "CALLER SIDE")
id := fmt.Sprintf("%d", s.ID+7000)
toid := fmt.Sprintf("%d", s.ID+21016)
fmt.Println("############################################################################## id : ", id)
fmt.Println("############################################################################## id : ", toid)
fmt.Println("############################################################################## id : ", s.TRTPTxPort)
ra := icsnet.NewNetAddrWithIPPort(simconf.GetSimTargetIP(), s.TSIPPort)
s.rsaddr = &ra
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "SIP address [%v] [%v]", s.lsaddr, s.rsaddr)
localSIPUDP := icsnet.NewUDP(s.lsaddr, s.rsaddr)
serr := localSIPUDP.Connect(s.lsaddr, s.rsaddr)
if serr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to Connect [%v]->[%v]", s.lsaddr, s.rsaddr)
return serr
}
/////////////////////
// send regi sip
fmt.Println("###################### regi")
if simconf.RegiCount != 0 {
regiCount := 0
for {
buf, rlen, err := simprocnew.NewReadSIP(s.ID, s.CallID, simconf.SimPhoneConfig.MYIP, s.TSIPPort, ra, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP)
if err != nil {
fmt.Println(err)
}
n := bytes.Index(buf[:rlen], []byte{32})
if string(buf[:n]) == "REGISTER" {
regiSip := simprocnew.NewSIPSignal("REGI", s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TSIPPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, buf, rlen)
if regiSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send Invite error [%s]", regiSip)
return regiSip
}
regiCount += 1
}
if regiCount == simconf.RegiCount {
break
}
}
}
// time.Sleep(time.Second * 2)
////////////////////
// get call flow //
///////////////////
// ra = icsnet.NewNetAddrWithIPPort(simconf.GetSimTargetIP(), s.TRTPTxPort)
// l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Start sending RTP[%s:%d]", ra.IPv4String, ra.Port)
// s.raddr = &ra
// s.localRTPUDP.SetRemoteAddr(s.raddr)
simScenarioConf := icsconf.GetSimScenarioConfig()
// var stopByeTimer *time.Ticker
for _, ord := range simScenarioConf.SipOrder.Order {
fmt.Println("######################################################## : ", strings.ToUpper(ord))
switch strings.ToUpper(ord) {
// case "WAIT": // set send bye time
// stopByeTimer = time.NewTicker(time.Second * time.Duration(simScenarioConf.SipOrder.StopTime))
case "BYE":
go func() {
// if stopByeTimer != nil {
// <-stopByeTimer.C
// }
sendSip := simprocnew.NewSIPSignal("BYE", s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, nil, 0)
if sendSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send bye error [%s]", sendSip)
return
}
}()
case "ACK":
sendSip := simprocnew.NewSIPSignal(strings.ToUpper(ord), s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, nil, 0)
if sendSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send SIP error (except BYE) [%s]", sendSip)
return sendSip
} else {
go func() {
buf, rlen, err := simprocnew.NewReadSIP(s.ID, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, ra, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP)
if err != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv BYE - %v", err)
return
} else {
fmt.Println(string(buf[:rlen]))
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Receved BYE Message : %s", string(buf[:rlen]))
// stopByeTimer.Stop()
sendSip := simprocnew.NewSIPSignal("BYE200", s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, nil, 0)
if sendSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send bye error [%s]", sendSip)
return
} else {
// s.mediaStart = 1
// s.wgMedia.Wait()
}
}
}()
}
case "TTS":
go s.ExpireReadRTP(rtpReadTimer)
for {
if s.sendRTPStatus {
break
}
}
case "STT":
// send rtp
ra = icsnet.NewNetAddrWithIPPort(simconf.GetSimTargetIP(), s.TRTPTxPort)
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Start sending RTP[%s:%d]", ra.IPv4String, ra.Port)
s.raddr = &ra
s.localRTPUDP.SetRemoteAddr(s.raddr)
s.wgMedia.Add(1)
go s.RunMedia(s.raddr.Port, s.PayloadType)
// s.mediaStart = 1
s.wgMedia.Wait()
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sending RTP Done!")
s.mediaStart = 2
case "DTMF":
default:
sendSip := simprocnew.NewSIPSignal(strings.ToUpper(ord), s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, nil, 0)
if sendSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send SIP error (except BYE) [%s]", sendSip)
return sendSip
}
}
}
s.localRTPUDP.Close()
wgRTPListen.Wait()
s.rtptimer.Stop()
return nil
}
func (s *SimPhone) RunMedia(port int, pt int) {
fmt.Println("#### RunMedia")
defer func() {
s.wgMedia.Done()
}()
l := icslog.GetIcsLog()
simconf := icsconf.GetSimConfig()
var voiceFileName string
if strings.Compare(simconf.IsCaller, "yes") == 0 {
voiceFileName = "./voice/9012-RX-1649749470147018876.raw"
} else {
voiceFileName = "./voice/9012-RX-1649749470147018876.raw"
}
fp, err := os.Open(voiceFileName)
if err != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to Voice file-%v", err)
if s.isCaller {
s.wgMedia.Done()
}
return
}
defer fp.Close()
fs, err := os.Stat(voiceFileName)
if err != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to Voice file-%v", err)
if s.isCaller {
s.wgMedia.Done()
}
return
}
fileLen := fs.Size()
voiceIdx := 0
voiceBuf := make([]byte, fileLen)
flen, err := fp.Read(voiceBuf)
if flen <= 0 || err != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to Voice file-%v", err)
if s.isCaller {
s.wgMedia.Done()
}
return
}
ra := icsnet.NewNetAddrWithIPPort(simconf.GetSimTargetIP(), s.TRTPTxPort)
s.localRTPUDP.SetRemoteAddr(&ra)
before := time.Now()
for {
<-s.rtptimer.C
s.rtptimer.Reset(time.Millisecond)
if s.mediaStart == 0 {
time.Sleep(time.Millisecond * 2)
// continue
} else if s.mediaStart == 2 {
break
}
now := time.Now()
var delta time.Duration = (time.Millisecond * 20) - now.Sub(before)
if delta < 0 {
time.Sleep((time.Millisecond * 20) + delta)
} else {
time.Sleep((time.Millisecond * 20) - delta)
}
before = now
r := icspacketgen.NewRTP()
rtppacket := r.MakeRTPData(uint8(pt), &s.Seq, &s.Timestamp, s.SSRC, voiceBuf[voiceIdx:voiceIdx+160])
voiceIdx += 160
if int64(voiceIdx+160) >= fileLen {
voiceIdx = len(voiceBuf) - 1
rtppacket = r.MakeRTPData(uint8(pt), &s.Seq, &s.Timestamp, s.SSRC, voiceBuf[voiceIdx:])
break
}
wlen, werr := s.localRTPUDP.WriteRTP(rtppacket)
if werr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to write RTP packet %d-%s{%v}", wlen, werr.GetMessage(), werr.GetError())
if s.isCaller {
s.wgMedia.Done()
}
return
}
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Voice data length %d-%d", voiceIdx, s.sentTime)
s.sendRTPStatus = false
}
func (s *SimPhone) String() string {
return fmt.Sprintf("ID: %d\nCall ID: %s\nPayload Type: %d\nSIP Port: %d\nTRTPTxPort: %d",
s.ID, s.CallID, s.PayloadType, s.SIPPort, s.TRTPTxPort)
}
func (s *SimPhone) ExpireReadRTP(t *time.Ticker) {
// s.sendRTPStatus = false
s.expTime = time.Now()
for t := range t.C {
// if s.sendRTPStatus {
// s.sendRTPStatus = false
// } else
if time.Now().Sub(s.expTime) >= time.Second {
fmt.Println(t)
s.sendRTPStatus = true
break
} else if s.sendRTPStatus {
continue
}
}
}

@ -0,0 +1,230 @@
package simproc
import (
"strconv"
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
)
const (
INVITE_STATE = 1 << iota
BYE_STATE
ACK_STATE
OK200_STATE
NONE_STATE = INVITE_STATE
UNKNOWN_STATE = 0xFFFF
)
const (
INVITE_METH = INVITE_STATE
ACK_METH = INVITE_STATE
BYE_METH = INVITE_STATE
OK200_METH = INVITE_STATE | BYE_STATE
UNKNOWN_METH = UNKNOWN_STATE
)
const (
MNAME_INVITE = 1 + iota
MNAME_ACK
MNAME_BYE
MNAME_OK200
MNAME_UNKNOWN
)
type SIPProc struct {
curState int
SIPHeader *SIPHeader
SDP *SDP
}
type SIPHeader struct {
ID int
Method string
From string
To string
CallID string
CSeq string
ContentType string
Payload string
}
type SDP struct {
Connection string
Port int
PayloadType int
}
func (p SIPProc) GetCurStatus() int {
return p.curState
}
func (p SIPProc) SetCurStatus(method int) {
p.curState = method
}
func (p SIPProc) GetMethod() int {
return p.SIPHeader.ID
}
func (p SIPProc) IsAllowMethod(method int) int {
return p.curState & method
}
func NewSIPProc(sip []byte) *SIPProc {
p := &SIPProc{curState: NONE_STATE}
p.SIPParse(sip)
p.SDPParse(p.SIPHeader.Payload)
return p
}
func NewSIPHeader() *SIPHeader {
h := &SIPHeader{}
return h
}
func (s *SIPProc) SIPParse(sip []byte) (method string) {
msg := string(sip)
hp := strings.Split(msg, "\r\n\r\n")
msgline := strings.Split(hp[0], "\r\n")
//linenum := len(msgline)
h := NewSIPHeader()
for iter, line := range msgline {
//fmt.Println(len(line), line)
if iter == 0 { //method line
method := strings.SplitN(line, " ", 2)
h.Method = method[0]
h.ID = getMethodID(h.Method)
} else {
headerline := strings.SplitN(line, ": ", 2)
switch strings.ToUpper(headerline[0]) {
case "FROM":
h.From = headerline[1]
case "TO":
h.To = headerline[1]
case "CALL-ID":
h.CallID = headerline[1]
case "CSEQ":
h.CSeq = headerline[1]
case "CONTENT-TYPE":
h.ContentType = headerline[1]
}
}
}
if len(hp) == 2 {
h.Payload = hp[1]
}
s.SIPHeader = h
/*
fmt.Println(s)
fmt.Println(*s.Header)
fmt.Println(">>>", s.Header.Method)
*/
return h.Method
}
func (s SIPProc) GetCSeq() string {
return s.SIPHeader.CSeq
}
func (s SIPProc) GetFrom() string {
return s.SIPHeader.From
}
func (s SIPProc) GetTo() string {
return s.SIPHeader.To
}
func (s SIPProc) GetCallID() string {
return s.SIPHeader.CallID
}
func getMethodID(method string) int {
switch method {
case "INVITE":
return INVITE_METH
case "BYE":
return BYE_METH
case "ACK":
return ACK_METH
case "SIP/2.0":
return OK200_METH
default:
return UNKNOWN_METH
}
}
func (s SIPProc) GetMethodNameID() int {
method := s.SIPHeader.Method
switch method {
case "INVITE":
return MNAME_INVITE
case "BYE":
return MNAME_BYE
case "ACK":
return MNAME_ACK
case "SIP/2.0":
return MNAME_OK200
default:
return MNAME_UNKNOWN
}
}
func GetMethodName(id int) (method string) {
switch id {
case MNAME_INVITE:
method = "INVITE"
case MNAME_BYE:
method = "BYE"
case MNAME_ACK:
method = "ACK"
case MNAME_OK200:
method = "200 OK"
case MNAME_UNKNOWN:
method = "UNKNOWN"
}
return method
}
func NewSDP() *SDP {
s := &SDP{}
return s
}
func (s *SIPProc) SDPParse(sdp string) {
if len(sdp) == 0 {
return
}
d := NewSDP()
sdplines := strings.Split(sdp, "\r\n")
for _, line := range sdplines {
sepline := strings.SplitN(line, "=", 2)
switch v := strings.ToUpper(sepline[0]); v {
case "C":
l := strings.Split(sepline[1], " ")
d.Connection = l[len(l)-1]
case "M":
l := strings.Split(sepline[1], " ")
d.Port, _ = strconv.Atoi(l[1])
d.PayloadType, _ = strconv.Atoi(l[3])
}
}
s.SDP = d
//fmt.Println("Connection:", d.Connection, ", Port:", d.Port, ", PayloadType:", d.PayloadType)
}
func (s SIPProc) GetRemoteRTPAddr() *icsnet.IcsNetAddr {
addr := icsnet.NewNetAddrWithIPPort(s.SDP.Connection, s.SDP.Port)
return &addr
}

@ -0,0 +1,135 @@
package simprocnew
import (
"fmt"
"strings"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
"gitlab.com/ics_cinnamon/voicegateway/sim/simproc"
"gitlab.com/ics_cinnamon/voicegateway/sim/siptemplate"
)
type SipCallFunc func(*SimCall)
type SimCall struct {
sipType string
cbFunc SipCallFunc
}
// s.Id = sessionid, id = sim agent id
func NewSIPSignal(sipType string, sessionId int, id string, toid string, ra icsnet.IcsNetAddr, callid string, ip string, rTPTxPort int, laddr *icsnet.IcsNetAddr, rsaddr *icsnet.IcsNetAddr, lsaddr *icsnet.IcsNetAddr, localSIPUDP *icsnet.IcsUDPNet, buf []byte, rlen int) *icserror.IcsError {
var sendTmpl string
var bye200 *icserror.IcsError
var sendMsg string
tmpl := siptemplate.GetTemplate()
l := icslog.GetIcsLog()
if strings.ToUpper(sipType) == "REGI" {
fmt.Println("#### Received REGI ")
p := simproc.NewSIPProc(buf[:rlen])
from := p.SIPHeader.From
id = strings.Split(strings.Split(from, "@")[0], ":")[1]
sendTmpl = tmpl.String(siptemplate.REGI_ID)
sendMsg = fmt.Sprintf(sendTmpl,
id, //start line
id, //from
callid,
id, //content
)
WriteSIP(sipType, sessionId, ra, callid, ip, rTPTxPort, laddr, rsaddr, lsaddr, sendMsg, localSIPUDP)
} else {
switch strings.ToUpper(sipType) {
case "INVITE":
sendTmpl = tmpl.String(siptemplate.INVITETMPL_ID)
sendMsg = fmt.Sprintf(sendTmpl,
id, //start line
id, // from
id, // to
callid, //call id
id, //contact
227, //content-length
ip, //c=
rTPTxPort, //o=
)
case "INVITE200":
case "ACK":
sendTmpl = tmpl.String(siptemplate.ACKTMPL_ID)
sendMsg = fmt.Sprintf(sendTmpl,
id, //start line
id, //from
id, //to
callid, //callid
id, //conatact
)
case "BYE":
sendTmpl = tmpl.String(siptemplate.BYETMPL_ID)
sendMsg = fmt.Sprintf(sendTmpl,
id, //start line
id, //from
id, //to
callid, //call id
)
case "BYE200":
sendTmpl = tmpl.String(siptemplate.OK200BYETMPL_ID)
sendMsg = fmt.Sprintf(sendTmpl,
id, //from
id, //to
callid, //callid
id, //contact
)
case "REFER":
case "NOTIFY":
case "NOTIFY200":
}
l.Printf(icslog.LOG_LEVEL_INFO, sessionId, "Call ID [%s]", callid)
WriteSIP(sipType, sessionId, ra, callid, ip, rTPTxPort, laddr, rsaddr, lsaddr, sendMsg, localSIPUDP)
if strings.ToUpper(sipType) != "ACK" && strings.ToUpper(sipType) != "BYE" {
_, _, err := NewReadSIP(sessionId, callid, ip, rTPTxPort, ra, laddr, rsaddr, lsaddr, localSIPUDP)
if err != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, sessionId, "Failed to recv SIP - %v", err)
return err
}
}
}
if bye200 != nil {
return bye200
}
return nil
}
func NewReadSIP(sessionId int, callid string, ip string, rTPTxPort int, ra icsnet.IcsNetAddr, laddr *icsnet.IcsNetAddr, rsaddr *icsnet.IcsNetAddr, lsaddr *icsnet.IcsNetAddr, localSIPUDP *icsnet.IcsUDPNet) ([]byte, int, *icserror.IcsError) {
l := icslog.GetIcsLog()
buf, remAddr, rlen, siperr := localSIPUDP.ReadSIP()
if siperr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, sessionId, "Failed to recv SIP - %v", siperr)
localSIPUDP.Close()
return nil, 0, siperr
} else {
fmt.Printf("####### Receved SIP Packet > \r\n%s \r\n", buf[:rlen])
l.Printf(icslog.LOG_LEVEL_INFO, sessionId, "Recved SIP Packet [%s:%d]->[%s:%d]>\n%s\n===================",
remAddr.IP.String(), remAddr.Port, rsaddr.IPv4String, rsaddr.Port, buf[:rlen])
}
return buf, rlen, nil
}
func WriteSIP(sipType string, sessionId int, ra icsnet.IcsNetAddr, callid string, ip string, rTPTxPort int, laddr *icsnet.IcsNetAddr, rsaddr *icsnet.IcsNetAddr, lsaddr *icsnet.IcsNetAddr, sendMsg string, localSIPUDP *icsnet.IcsUDPNet) *icserror.IcsError {
l := icslog.GetIcsLog()
l.Printf(icslog.LOG_LEVEL_INFO, sessionId, "Call ID [%s]", callid)
fmt.Println("send msg", sendMsg)
_, werr := localSIPUDP.Write([]byte(sendMsg))
if werr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, sessionId, "Failed to send SIP - %v", werr)
localSIPUDP.Close()
return werr
} else {
l.Printf(icslog.LOG_LEVEL_INFO, sessionId, "Send SIP Packet [%s:%d]->[%s:%d]>\n%s\n===================",
ip, lsaddr.Port, rsaddr.IPv4String, rsaddr.Port, sendMsg)
return nil
}
}

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<SIMVC version="1.0.0.0">
<ISCALLER>yes</ISCALLER>
<CHANNELS>1</CHANNELS>
<REPEAT>1</REPEAT>
<TARGET ip="192.168.0.230" sipport="6000" rtpport="30000"/>
<SIM myip="192.168.0.26" sipport="6000" rtpport="30000"/>
<LOG>
<PATH>log</PATH>
<DISKLIMIT>100</DISKLIMIT>
<LEVEL>DEBUG2</LEVEL>
<OUTPUT>file</OUTPUT>
<ROTATE size="100" num="10" yesno="yes"/>
</LOG>
</SIMVC>

@ -0,0 +1,161 @@
package siptemplate
import (
"fmt"
"sync"
)
type SIPTmpl struct {
Template []string
}
const (
INVITETMPL_ID = iota
ACKTMPL_ID
BYETMPL_ID
OK200INVITETMPL_ID
OK200BYETMPL_ID
REGI_ID
MAX_ID
)
var (
inviteTmpl string
ackTmpl string
byeTmpl string
ok200InviteTmpl string
ok200ByeTmpl string
regiTmpl string
)
func init() {
inviteTmpl = fmt.Sprint("INVITE sip:%s@192.168.0.21:3000;transport=udp SIP/2.0\r\n" +
"Via: SIP/2.0/UDP 192.168.0.21:5090;branch=z9hG4bKac596453013\r\n" +
"Max-Forwards: 69\r\n" +
// "From: <sip:%s@192.168.0.21>;tag=1c867251551\r\n" +
"From: <sip:%s@192.168.0.21>;tag=1c867251551\r\n" +
"To: <sip:%s@192.168.0.21;user=phone>\r\n" +
"Call-ID: %s\r\n" +
"CSeq: 1 INVITE\r\n" +
"Contact: <sip:%s@192.168.0.21:3000>\r\n" +
"Supported: em,100rel,timer,replaces,path,resource-priority,sdp-anat\r\n" +
"Allow: REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE\r\n" +
"User-Agent: M800B/v.7.20A.204.759\r\n" +
"Content-Type: application/sdp\r\n" +
"Content-Length: %d\r\n" +
"\r\n" +
"v=0\r\n" +
"o=AudiocodesGW 1879481090 705321541 IN IP4 192.168.0.21\r\n" +
"s=Phone-Call\r\n" +
// "c=IN IP4 192.168.0.222\r\n" + // IP4는 로컬이 아니라서 고정을 해도될듯
"c=IN IP4 %s\r\n" +
"t=0 0\r\n" +
"m=audio %d RTP/AVP 8 0 18 101\r\n" +
// "m=audio %d RTP/AVP 8 0 18 101\r\n" +
"a=ptime:20\r\n" +
"a=sendrecv\r\n" +
"a=rtpmap:8 PCMA/8000\r\n" +
"a=rtpmap:0 PCMU/8000\r\n" +
"a=rtpmap:18 G729/8000\r\n" +
"a=fmtp:18 annexb=no\r\n" +
"a=rtpmap:101 telephone-event/8000\r\n" +
"a=fmtp:101 0-15")
ackTmpl = fmt.Sprint("ACK sip:%s@192.168.0.21:5090;transport=udp SIP/2.0\r\n" +
"Via: SIP/2.0/UDP 192.168.0.21:5090;branch=z9hG4bKac390123597\r\n" +
"Max-Forwards: 69\r\n" +
"From: <sip:%s@192.168.0.221>;tag=1c867251551\r\n" +
"To: <sip:%s@192.168.0.21;user=phone>;tag=MTY0OTExODIxODQxMzQ5NTY1Mw--\r\n" +
"Call-ID: %s\r\n" +
"CSeq: 1 ACK\r\n" +
"Contact: <sip:%s@192.168.0.21:5090>\r\n" +
"Supported: em,timer,replaces,path,resource-priority\r\n" +
"Allow: REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE\r\n" +
"User-Agent: M800B/v.7.20A.204.759\r\n" +
"Content-Length: 0")
byeTmpl = fmt.Sprint("BYE sip:%s@192.168.0.21:5090;transport=udp SIP/2.0\r\n" +
"Via: SIP/2.0/UDP 192.168.0.222:5090;branch=z9hG4bKac1246799505\r\n" +
"Max-Forwards: 69\r\n" +
"From: <sip:%s@192.168.0.221>;tag=1c867251551\r\n" +
"To: <sip:%s@192.168.0.21;user=phone>;tag=MTY0OTExODIxODQxMzQ5NTY1Mw--\r\n" +
"Call-ID: %s\r\n" +
"CSeq: 2 BYE\r\n" +
"Supported: em,timer,replaces,path,resource-priority\r\n" +
"Allow: REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE\r\n" +
"User-Agent: M800B/v.7.20A.204.759\r\n" +
"Reason: Q.850 ;cause=16\r\n" +
"Content-Length: 0")
ok200InviteTmpl = fmt.Sprint("SIP/2.0 200 OK\r\n" +
"Via: SIP/2.0/UDP 192.168.0.21:5090;branch=z9hG4bKac596453013\r\n" +
"From: <sip:%s@192.168.0.221>;tag=1c867251551\r\n" +
"To: <sip:%s@192.168.0.21;user=phone>;tag=MTY0OTExODIxODQxMzQ5NTY1Mw--\r\n" +
"Call-ID: %s\r\n" +
"CSeq: 1 INVITE\r\n" +
"Contact: <sip:%s@%d:%d;transport=udp>\r\n" +
// "Contact: <sip:%s@192.168.0.21:5090;transport=udp>\r\n" +
"Allow: REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE\r\n" +
"Supported: timer, path, replaces, sdp-anat\r\n" +
"User-Agent: iCOMSYS_CALLAGENT\r\n" +
"Content-Type: application/sdp\r\n" +
"Content-Length: 226\r\n" +
"\r\n" +
"v=0\r\n" +
"o=iCOMSYS-AGENT 1649118218 1649118219 IN IP4 192.168.0.21\r\n" +
"s=\r\n" +
// "c=IN IP4 192.168.0.21\r\n" +
"c=IN IP4 %s\r\n" +
"t=0 0\r\n" +
"m=audio 21000 RTP/AVP 8 101 \r\n" +
"a=rtpmap:8 PCMA/8000\r\n" +
"a=ptime:20\r\n" +
"a=sendrecv\r\n" +
"a=rtpmap:101 telephone-event/8000\r\n" +
"a=fmtp:101 0-15")
ok200ByeTmpl = fmt.Sprint("SIP/2.0 200 OK\r\n" +
"Via: SIP/2.0/UDP 192.168.0.21:5090;branch=z9hG4bKac1520651703\r\n" +
"From: <sip:%s@192.168.0.21>;tag=1c1838414031\r\n" +
"To: <sip:%s@192.168.0.21;user=phone>;tag=MTY0ODQyNzQ2NTU4MzMzNDYyMg--\r\n" +
"Call-ID: %s\r\n" +
"CSeq: 2 BYE\r\n" +
"Contact: <sip:%s@192.168.0.21:5090;transport=udp>\r\n" +
"Allow: REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE\r\n" +
"User-Agent: iCOMSYS_CALLAGENT\r\n")
regiTmpl = fmt.Sprint("SIP/2.0 200 OK\r\n" +
"Via: SIP/2.0/UDP 192.168.0.21;received=192.168.0.21;rport=5090;branch=ZTg1OTUyNWQtMTc3NC00YjJmLWIyZWUtZjg5OTFkOGU0OTU5\r\n" +
"From: <sip:%s@192.168.0.21>;tag=MTY0ODcwMDU1MzQ5OTM3NzQ2Mw--\r\n" +
"To: <sip:%s@192.168.0.21>;tag=1c2023025228\r\n" +
"Call-ID: %s@192.168.0.21\r\n" +
"CSeq: 0 REGISTER\r\n" +
"Contact: <sip:%s@192.168.0.21:5090;transport=udp>;expires=3600\r\n" +
"Expires: 3600\r\n" +
"Content-Length: 0\r\n\r\n")
}
var onceTemplate sync.Once
var gTemplate *SIPTmpl
func GetTemplate() *SIPTmpl {
return gTemplate
}
func Init() {
onceTemplate.Do(func() {
gTemplate = &SIPTmpl{}
gTemplate.Template = make([]string, MAX_ID)
gTemplate.Template[INVITETMPL_ID] = inviteTmpl
gTemplate.Template[ACKTMPL_ID] = ackTmpl
gTemplate.Template[BYETMPL_ID] = byeTmpl
gTemplate.Template[OK200INVITETMPL_ID] = ok200InviteTmpl
gTemplate.Template[OK200BYETMPL_ID] = ok200ByeTmpl
gTemplate.Template[REGI_ID] = regiTmpl
})
}
func (s *SIPTmpl) String(id int) string {
return s.Template[id]
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

@ -0,0 +1,444 @@
package sipasm
import (
"encoding/base64"
"fmt"
"strings"
"time"
uuid "github.com/satori/go.uuid"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)
const (
MAX_HEADER_OVERLAP int = 100
MAX_CSEQ uint32 = 4294967294
)
const (
SDP_SENDRECV = 0
SDP_SENDONLY = 1
SDP_RECVONLY = 2
)
///////////////////////////////
type headerOverlap struct {
length int
headers [MAX_HEADER_OVERLAP]string
}
func NewHeaderOverlap() *headerOverlap {
var h headerOverlap
h.length = 0
return &h
}
func (h *headerOverlap) AddHeader(msg string) {
h.headers[h.length] = msg
h.length++
}
// if idx is less than 0, then returns last header
func (h headerOverlap) GetHeader(idx int) string {
if idx < 0 {
return h.headers[h.length]
} else {
return h.headers[idx]
}
}
func (h headerOverlap) GetLength() int {
return h.length
}
/////////////////////////////////
type SIPMessage struct {
Method string
header map[ICSSIP_HEADER_TYPE]*headerOverlap
HeaderString string
BodyString string
branch string
tag string
recvedSIP *icspacketparser.SIP
SDP *SDPMessage
}
func NewSIPMessage(methodType ICSSIP_METHOD_TYPE, value string) *SIPMessage {
if methodType >= ICSSIP_METHOD_MAX {
return nil
}
var sipmessage SIPMessage
sipmessage.header = make(map[ICSSIP_HEADER_TYPE]*headerOverlap)
for iter := 0; iter < MAX_HEADER_OVERLAP; iter++ {
sipmessage.header[ICSSIP_HEADER_TYPE(iter)] = NewHeaderOverlap()
}
msg := fmt.Sprintf("%s SIP/2.0", value)
sipmessage.Method = fmt.Sprintf(ICSSIP_METHOD_STRING[methodType], msg)
return &sipmessage
}
func NewSIPResponse(sip *icspacketparser.SIP, statusCode int) *SIPMessage {
var sipmessage SIPMessage
sipmessage.header = make(map[ICSSIP_HEADER_TYPE]*headerOverlap)
for iter := 0; iter < MAX_HEADER_OVERLAP; iter++ {
sipmessage.header[ICSSIP_HEADER_TYPE(iter)] = NewHeaderOverlap()
}
sipmessage.recvedSIP = sip
msg := ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_TYPE(statusCode)]
allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
//msg := fmt.Sprintf("%s", ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_TYPE(statusCode)])
sipmessage.Method = fmt.Sprintf(ICSSIP_METHOD_STRING[ICSSIP_METHOD_SIP20], msg)
for iter := 0; iter < len(sip.Via); iter++ {
sipmessage.AddSIPHeader(ICSSIP_HEADER_VIA, sip.Via[iter])
}
//maxforwards := fmt.Sprintf("%d", sip.MaxForwards)
//sipmessage.AddSIPHeader(ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
sipmessage.AddSIPHeader(ICSSIP_HEADER_FROM, sip.From)
var toTag string
if statusCode != 100 && !strings.Contains(sip.To, ";tag") {
toTag = fmt.Sprintf("%s;tag=%s", sip.To, GenerateTag())
sipmessage.AddSIPHeader(ICSSIP_HEADER_TO, toTag)
//fmt.Printf("##### sip.to: %s, toTag: %s\n", sip.To, toTag)
} else {
sipmessage.AddSIPHeader(ICSSIP_HEADER_TO, sip.To)
}
sipmessage.AddSIPHeader(ICSSIP_HEADER_CALL_ID, sip.CallID)
sipmessage.AddSIPHeader(ICSSIP_HEADER_CSEQ, sip.Cseq)
sipmessage.AddSIPHeader(ICSSIP_HEADER_ALLOW, allow)
return &sipmessage
}
/////////////////////////////////
//SIP operator
func (s *SIPMessage) AddSIPHeader(headerType ICSSIP_HEADER_TYPE, value ...interface{}) string {
if headerType >= ICSSIP_HEADER_MAX {
return ""
}
var msg string
if len(value) <= 0 {
msg = fmt.Sprint(ICSSIP_HEADER_STRING[headerType])
} else {
msg = fmt.Sprintf(ICSSIP_HEADER_STRING[headerType], value...)
//fmt.Printf(ICSSIP_HEADER_STRING[headerType], value...)
}
//fmt.Printf(">>>>%s, %s\n", ICSSIP_HEADER_STRING[headerType], value...)
h := s.header[headerType]
h.AddHeader(msg)
return h.GetHeader(-1)
}
func (s SIPMessage) SearchSIPHeader(headerType ICSSIP_HEADER_TYPE) *headerOverlap {
if headerType < ICSSIP_HEADER_TYPE(0) {
return nil
}
h := s.header[headerType]
length := h.GetLength()
for iter := 0; iter < length; iter++ {
f := h.GetHeader(iter)
if strings.Contains(ICSSIP_HEADER_STRING[headerType], f) {
return h
}
}
return nil
}
func (s SIPMessage) SearchSIPHeaderWithString(headerName string) *headerOverlap {
if len(headerName) <= 0 {
return nil
}
MSG := strings.ToUpper(headerName)
htype := ICSSIP_HEADER_STRING2TYPE[MSG]
h := s.header[htype]
length := h.GetLength()
for iter := 0; iter < length; iter++ {
f := h.GetHeader(iter)
if strings.Contains(ICSSIP_HEADER_STRING[htype], f) {
return h
}
}
return nil
}
//if idxOfOverlap is less than 0, then deletes whole the HeaderOverlap for that headerType
func (s *SIPMessage) DelSIPHeader(headerType ICSSIP_HEADER_TYPE, idxOfOverlap int) bool {
if headerType < ICSSIP_HEADER_TYPE(0) {
return false
}
if idxOfOverlap < 0 {
h := s.SearchSIPHeader(headerType)
if h == nil {
return false
}
length := h.GetLength()
for iter := 0; iter < length; iter++ {
h.headers[iter] = ""
}
h.length = 0
} else {
h := s.SearchSIPHeader(headerType)
if h == nil {
return false
}
h.headers[idxOfOverlap] = ""
h.length--
}
return true
}
//replaces a header to point the headerType to value. it replace only first(0th) overlapped header in the HeaderOverlap
//DO NOT USE for VIA header
func (s *SIPMessage) ReplaceSIPHeader(headerType ICSSIP_HEADER_TYPE, value string) string {
if headerType < ICSSIP_HEADER_TYPE(0) {
return ""
}
if len(value) <= 0 {
return ""
}
h := s.SearchSIPHeader(headerType)
h.headers[0] = value
return h.headers[0]
}
func (s *SIPMessage) GetSIPHeader(headerType ICSSIP_HEADER_TYPE) (headers *[MAX_HEADER_OVERLAP]string) {
if headerType < ICSSIP_HEADER_TYPE(0) {
return headers
}
h := s.header[headerType].headers
return &h
}
func (s SIPMessage) String() (message string) {
if len(s.Method) == 0 {
return ""
}
message = s.Method
for iter := 0; iter < int(ICSSIP_HEADER_MAX); iter++ {
h := s.header[ICSSIP_HEADER_TYPE(iter)]
length := h.GetLength()
for iter2 := 0; iter2 < length; iter2++ {
msg := h.GetHeader(iter2)
if len(msg) != 0 {
message += msg
}
}
}
if s.SDP != nil {
message += s.SDP.String()
}
/* TODO: add payload to message
if len(s.Header[ICSSIP_HEADER_CONTENT_TYPE]) != 0 {
}
*/
return message
}
//////////////////////////////////
// SDP operator
type SDPMessage struct {
connection string
origin string
sessionName string
media []*SDPMedia
}
type SDPMedia struct {
mediaType ICSSDP_MEDIA_TYPE
port int
rtpmap []*RTPMap
}
type RTPMap struct {
payloadNum int
ptime int
fmtp string
sendrecv string
}
//only audio media allowed
func NewSDPMessage(ip string, port int, audFormats []string, sendrecv int) *SDPMessage {
var sdpMessage SDPMessage
sessID := time.Now().Local().Unix()
sessVer := sessID + 1
oLine := fmt.Sprintf("AudiocodesGW-AGENT %d %d IN IP4 %s", sessID, sessVer, ip)
connection := fmt.Sprintf("IN IP4 %s", ip)
sdpMessage = SDPMessage{connection: connection,
origin: oLine,
sessionName: ""}
sdpMessage.media = make([]*SDPMedia, 1)
sdpMessage.media[0] = NewSDPMedia(ICSSDP_MEDIA_AUDIO, port, audFormats, sendrecv)
return &sdpMessage
}
func (s SDPMessage) String() string {
sdp := fmt.Sprintf("v=0\r\no=%s\r\ns=%s\r\nc=%s\r\nt=0 0\r\n%s", s.origin, s.sessionName, s.connection, s.media[0].String())
return sdp
}
func NewSDPMedia(audvid ICSSDP_MEDIA_TYPE, port int, audFormats []string, sendrecv int) *SDPMedia {
sdpMedia := SDPMedia{mediaType: audvid,
port: port}
fmtLen := len(audFormats)
sdpMedia.rtpmap = make([]*RTPMap, fmtLen+1)
strSendrecv := "sendrecv"
if sendrecv == SDP_SENDONLY {
strSendrecv = "sendonly"
} else if sendrecv == SDP_RECVONLY {
strSendrecv = "recvonly"
}
var iter int
for iter = 0; iter < fmtLen; iter++ {
format := strings.ToUpper(audFormats[iter])
//fmt.Println("set rtpmap>>>", format)
switch format {
case "PCMU":
sdpMedia.rtpmap[iter] = NewRTPMap(0, 20, "", strSendrecv)
case "PCMA":
sdpMedia.rtpmap[iter] = NewRTPMap(8, 20, "", strSendrecv)
case "G729":
fallthrough
case "G.729":
sdpMedia.rtpmap[iter] = NewRTPMap(18, 20, "annexb=no", strSendrecv)
default:
}
}
//telephone event
sdpMedia.rtpmap[iter] = NewRTPMap(101, 20, "0-15", "sendrecv")
return &sdpMedia
}
func (m SDPMedia) String() string {
var media string
var payloadNum string
var rtpmap string
plen := len(m.rtpmap)
for iter := 0; iter < plen; iter++ {
payloadNum += fmt.Sprintf("%d ", m.rtpmap[iter].payloadNum)
rtpmap += m.rtpmap[iter].String()
}
media = fmt.Sprintf("m=audio %d RTP/AVP %s\r\n%s", m.port, payloadNum, rtpmap)
return media
}
func NewRTPMap(payloadNum int, ptime int, fmtp string, sendrecv string) *RTPMap {
rtpMap := RTPMap{
payloadNum: payloadNum,
ptime: ptime,
fmtp: fmtp,
sendrecv: sendrecv,
}
return &rtpMap
}
func (r RTPMap) String() string {
var name string
switch r.payloadNum {
case 0:
name = "PCMU"
case 8:
name = "PCMA"
case 18:
name = "G729"
case 101:
name = "telephone-event"
}
var rtpmap string
if r.payloadNum == 101 {
rtpmap = fmt.Sprintf("a=rtpmap:%d %s/8000\r\na=fmtp:%d %s\r\n",
r.payloadNum, name, r.payloadNum, r.fmtp)
} else {
if len(r.fmtp) > 0 {
rtpmap = fmt.Sprintf("a=rtpmap:%d %s/8000\r\na=fmtp:%d %s\r\na=ptime:%d\r\na=%s\r\n",
r.payloadNum, name, r.payloadNum, r.fmtp, r.ptime, r.sendrecv)
} else {
rtpmap = fmt.Sprintf("a=rtpmap:%d %s/8000\r\na=ptime:%d\r\na=%s\r\n",
r.payloadNum, name, r.ptime, r.sendrecv)
}
}
return rtpmap
}
//////////////////////////////////
func GenerateCallID(postfix string) (callid string) {
uuid := uuid.NewV4()
callid = fmt.Sprintf("%s%s", uuid.String(), postfix)
return callid
}
func GenerateBranch() (branch string) {
uuid := uuid.NewV4()
branch = base64.StdEncoding.EncodeToString([]byte(uuid.String()))
b := []byte(branch)
length := len(b)
for iter := 0; iter < length; iter++ {
if b[iter] == 0x3d {
b[iter] = '-'
}
}
branch = string(b)
return branch
}
func GenerateTag() (tag string) {
now := fmt.Sprintf("%d", time.Now().UnixNano())
t := base64.StdEncoding.EncodeToString([]byte(now))
b := []byte(t)
length := len(b)
for iter := 0; iter < length; iter++ {
if b[iter] == 0x3d {
b[iter] = '-'
}
}
tag = string(b)
return tag
}

@ -0,0 +1,438 @@
package sipasm
type ICSSIP_METHOD_TYPE uint
type ICSSIP_HEADER_TYPE uint
type ICSSIP_STATUSCODE_TYPE uint
var ICSSIP_METHOD_STRING map[ICSSIP_METHOD_TYPE]string
var ICSSIP_HEADER_STRING map[ICSSIP_HEADER_TYPE]string
var ICSSIP_STATUSCODE_STRING map[ICSSIP_STATUSCODE_TYPE]string
var ICSSIP_HEADER_STRING2TYPE map[string]ICSSIP_HEADER_TYPE
type ICSSDP_MEDIA_TYPE int
const (
ICSSDP_MEDIA_AUDIO ICSSDP_MEDIA_TYPE = iota
ICSSDP_MEDIA_VIDEO
)
const (
ICSSIP_METHOD_REGISTER ICSSIP_METHOD_TYPE = iota
ICSSIP_METHOD_ACK
ICSSIP_METHOD_INVITE
ICSSIP_METHOD_BYE
ICSSIP_METHOD_CANCEL
ICSSIP_METHOD_INFO
ICSSIP_METHOD_PRACK
ICSSIP_METHOD_SUBSCRIBE
ICSSIP_METHOD_NOTIFY
ICSSIP_METHOD_PUBLISH
ICSSIP_METHOD_REFER
ICSSIP_METHOD_MESSAGE
ICSSIP_METHOD_UPDATE
ICSSIP_METHOD_OPTIONS
ICSSIP_METHOD_SIP20
ICSSIP_METHOD_MAX
)
const (
ICSSIP_HEADER_VIA ICSSIP_HEADER_TYPE = iota
ICSSIP_HEADER_MAX_FORWARDS
ICSSIP_HEADER_FROM
ICSSIP_HEADER_TO
ICSSIP_HEADER_CALL_ID
ICSSIP_HEADER_CSEQ
ICSSIP_HEADER_CONTACT
ICSSIP_HEADER_ACCEPT
ICSSIP_HEADER_ACCEPT_ENCODING
ICSSIP_HEADER_ACCEPT_LANGUAGE
ICSSIP_HEADER_ALERT_INFO
ICSSIP_HEADER_ALLOW
ICSSIP_HEADER_AUTHENTICATION_INFO
ICSSIP_HEADER_AUTHORIZATION
ICSSIP_HEADER_CALL_INFO
ICSSIP_HEADER_DATE
ICSSIP_HEADER_ERROR_INFO
ICSSIP_HEADER_EXPIRES
ICSSIP_HEADER_IN_REPLY_TO
ICSSIP_HEADER_MIN_EXPIRES
ICSSIP_HEADER_MIME_VERSION
ICSSIP_HEADER_ORGANIZATION
ICSSIP_HEADER_PRIORITY
ICSSIP_HEADER_PROXY_AUTHENTICATE
ICSSIP_HEADER_PROXY_AUTHORIZATION
ICSSIP_HEADER_PROXY_REQUIRE
ICSSIP_HEADER_RECORD_ROUTE
ICSSIP_HEADER_REFER_TO
ICSSIP_HEADER_REPLY_TO
ICSSIP_HEADER_REQUIRE
ICSSIP_HEADER_RETRY_AFTER
ICSSIP_HEADER_ROUTE
ICSSIP_HEADER_RSEQ
ICSSIP_HEADER_RACK
ICSSIP_HEADER_SERVER
ICSSIP_HEADER_SUBJECT
ICSSIP_HEADER_SUPPORTED
ICSSIP_HEADER_TIMESTAMP
ICSSIP_HEADER_UNSUPPORTED
ICSSIP_HEADER_USER_AGENT
ICSSIP_HEADER_WARNING
ICSSIP_HEADER_WWW_AUTHENTICATE
ICSSIP_HEADER_CONTENT_TYPE
ICSSIP_HEADER_CONTENT_DISPOSITION
ICSSIP_HEADER_CONTENT_ENCODING
ICSSIP_HEADER_CONTENT_LANGUAGE
ICSSIP_HEADER_CONTENT_LENGTH
ICSSIP_HEADER_TERMINATOR
ICSSIP_HEADER_NOT_DEFINED
ICSSIP_HEADER_MAX
)
const (
ICSSIP_STATUSCODE_100 ICSSIP_STATUSCODE_TYPE = 100
ICSSIP_STATUSCODE_180 ICSSIP_STATUSCODE_TYPE = 180
ICSSIP_STATUSCODE_181 ICSSIP_STATUSCODE_TYPE = 181
ICSSIP_STATUSCODE_182 ICSSIP_STATUSCODE_TYPE = 182
ICSSIP_STATUSCODE_183 ICSSIP_STATUSCODE_TYPE = 183
ICSSIP_STATUSCODE_200 ICSSIP_STATUSCODE_TYPE = 200
ICSSIP_STATUSCODE_300 ICSSIP_STATUSCODE_TYPE = 300
ICSSIP_STATUSCODE_301 ICSSIP_STATUSCODE_TYPE = 301
ICSSIP_STATUSCODE_302 ICSSIP_STATUSCODE_TYPE = 302
ICSSIP_STATUSCODE_305 ICSSIP_STATUSCODE_TYPE = 305
ICSSIP_STATUSCODE_380 ICSSIP_STATUSCODE_TYPE = 380
ICSSIP_STATUSCODE_400 ICSSIP_STATUSCODE_TYPE = 400
ICSSIP_STATUSCODE_401 ICSSIP_STATUSCODE_TYPE = 401
ICSSIP_STATUSCODE_402 ICSSIP_STATUSCODE_TYPE = 402
ICSSIP_STATUSCODE_403 ICSSIP_STATUSCODE_TYPE = 403
ICSSIP_STATUSCODE_404 ICSSIP_STATUSCODE_TYPE = 404
ICSSIP_STATUSCODE_405 ICSSIP_STATUSCODE_TYPE = 405
ICSSIP_STATUSCODE_406 ICSSIP_STATUSCODE_TYPE = 406
ICSSIP_STATUSCODE_407 ICSSIP_STATUSCODE_TYPE = 407
ICSSIP_STATUSCODE_408 ICSSIP_STATUSCODE_TYPE = 408
ICSSIP_STATUSCODE_410 ICSSIP_STATUSCODE_TYPE = 410
ICSSIP_STATUSCODE_413 ICSSIP_STATUSCODE_TYPE = 413
ICSSIP_STATUSCODE_414 ICSSIP_STATUSCODE_TYPE = 414
ICSSIP_STATUSCODE_415 ICSSIP_STATUSCODE_TYPE = 415
ICSSIP_STATUSCODE_416 ICSSIP_STATUSCODE_TYPE = 416
ICSSIP_STATUSCODE_420 ICSSIP_STATUSCODE_TYPE = 420
ICSSIP_STATUSCODE_421 ICSSIP_STATUSCODE_TYPE = 421
ICSSIP_STATUSCODE_423 ICSSIP_STATUSCODE_TYPE = 423
ICSSIP_STATUSCODE_480 ICSSIP_STATUSCODE_TYPE = 480
ICSSIP_STATUSCODE_481 ICSSIP_STATUSCODE_TYPE = 481
ICSSIP_STATUSCODE_482 ICSSIP_STATUSCODE_TYPE = 482
ICSSIP_STATUSCODE_483 ICSSIP_STATUSCODE_TYPE = 483
ICSSIP_STATUSCODE_484 ICSSIP_STATUSCODE_TYPE = 484
ICSSIP_STATUSCODE_485 ICSSIP_STATUSCODE_TYPE = 485
ICSSIP_STATUSCODE_486 ICSSIP_STATUSCODE_TYPE = 486
ICSSIP_STATUSCODE_487 ICSSIP_STATUSCODE_TYPE = 487
ICSSIP_STATUSCODE_488 ICSSIP_STATUSCODE_TYPE = 488
ICSSIP_STATUSCODE_491 ICSSIP_STATUSCODE_TYPE = 491
ICSSIP_STATUSCODE_493 ICSSIP_STATUSCODE_TYPE = 493
ICSSIP_STATUSCODE_500 ICSSIP_STATUSCODE_TYPE = 500
ICSSIP_STATUSCODE_501 ICSSIP_STATUSCODE_TYPE = 551
ICSSIP_STATUSCODE_502 ICSSIP_STATUSCODE_TYPE = 502
ICSSIP_STATUSCODE_503 ICSSIP_STATUSCODE_TYPE = 503
ICSSIP_STATUSCODE_504 ICSSIP_STATUSCODE_TYPE = 594
ICSSIP_STATUSCODE_505 ICSSIP_STATUSCODE_TYPE = 555
ICSSIP_STATUSCODE_513 ICSSIP_STATUSCODE_TYPE = 513
ICSSIP_STATUSCODE_600 ICSSIP_STATUSCODE_TYPE = 600
ICSSIP_STATUSCODE_603 ICSSIP_STATUSCODE_TYPE = 603
ICSSIP_STATUSCODE_604 ICSSIP_STATUSCODE_TYPE = 604
ICSSIP_STATUSCODE_606 ICSSIP_STATUSCODE_TYPE = 605
)
func init() {
//init templetes
initMethodString()
initHeaderString()
initStatusCodeString()
}
func initMethodString() {
ICSSIP_METHOD_STRING = make(map[ICSSIP_METHOD_TYPE]string)
ICSSIP_METHOD_STRING[ICSSIP_METHOD_REGISTER] = "REGISTER %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_ACK] = "ACK %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_INVITE] = "INVITE %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_BYE] = "BYE %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_CANCEL] = "CANCEL %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_INFO] = "INFO %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_PRACK] = "PRACK %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_SUBSCRIBE] = "SUBSCRIBE %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_NOTIFY] = "NOTIFY %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_PUBLISH] = "PUBLISH %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_REFER] = "REFER %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_MESSAGE] = "MESSAGE %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_UPDATE] = "UPDATE %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_OPTIONS] = "OPTIONS %s\r\n"
ICSSIP_METHOD_STRING[ICSSIP_METHOD_SIP20] = "SIP/2.0 %s\r\n"
}
func initHeaderString() {
ICSSIP_HEADER_STRING = make(map[ICSSIP_HEADER_TYPE]string)
ICSSIP_HEADER_STRING[ICSSIP_HEADER_ACCEPT] = "Accept: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_ACCEPT_ENCODING] = "Accept-Encoding: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_ACCEPT_LANGUAGE] = "Accept-Language: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_ALERT_INFO] = "Alert-Info: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_ALLOW] = "Allow: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_AUTHENTICATION_INFO] = "Authentication-Info: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_AUTHORIZATION] = "Authorization: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CALL_ID] = "Call-ID: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CALL_INFO] = "Call-Info: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CONTACT] = "Contact: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CONTENT_DISPOSITION] = "Content-Disposition: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CONTENT_ENCODING] = "Content-Encoding: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CONTENT_LANGUAGE] = "Content-Language: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CONTENT_LENGTH] = "Content-Length: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CONTENT_TYPE] = "Content-Type: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_CSEQ] = "CSeq: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_DATE] = "Date: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_ERROR_INFO] = "Error-Info: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_EXPIRES] = "Expires: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_FROM] = "From: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_IN_REPLY_TO] = "In-Reply-To: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_MAX_FORWARDS] = "Max-Forwards: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_MIN_EXPIRES] = "Min-Expires: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_MIME_VERSION] = "Mime-Version: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_ORGANIZATION] = "Organization: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_PRIORITY] = "Priority: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_PROXY_AUTHENTICATE] = "Proxy-Authenticate: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_PROXY_AUTHORIZATION] = "Proxy-Authorization: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_PROXY_REQUIRE] = "Proxy-Require: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_RECORD_ROUTE] = "Record-Route: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_REPLY_TO] = "Reply-To: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_REFER_TO] = "Refer-To: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_REQUIRE] = "Require: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_RETRY_AFTER] = "Retry-After: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_ROUTE] = "Route: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_RACK] = "RAck: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_RSEQ] = "RSeq: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_SERVER] = "Server: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_SUBJECT] = "Subject: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_SUPPORTED] = "Supported: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_TIMESTAMP] = "Timestamp: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_TO] = "To: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_UNSUPPORTED] = "Unsupported: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_USER_AGENT] = "User-Agent: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_VIA] = "Via: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_WARNING] = "Warning: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_WWW_AUTHENTICATE] = "WWW-Authenticate: %s\r\n"
ICSSIP_HEADER_STRING[ICSSIP_HEADER_TERMINATOR] = "\r\n"
ICSSIP_HEADER_STRING2TYPE = make(map[string]ICSSIP_HEADER_TYPE)
ICSSIP_HEADER_STRING2TYPE["ACCEPT"] = ICSSIP_HEADER_ACCEPT
ICSSIP_HEADER_STRING2TYPE["ACCEPT-ENCODING"] = ICSSIP_HEADER_ACCEPT_ENCODING
ICSSIP_HEADER_STRING2TYPE["ACCEPT-LANGUAGE"] = ICSSIP_HEADER_ACCEPT_LANGUAGE
ICSSIP_HEADER_STRING2TYPE["ALERT-INFO"] = ICSSIP_HEADER_ALERT_INFO
ICSSIP_HEADER_STRING2TYPE["ALLOW"] = ICSSIP_HEADER_ALLOW
ICSSIP_HEADER_STRING2TYPE["AUTHENTICATION-INFO"] = ICSSIP_HEADER_AUTHENTICATION_INFO
ICSSIP_HEADER_STRING2TYPE["AUTHORIZATION"] = ICSSIP_HEADER_AUTHORIZATION
ICSSIP_HEADER_STRING2TYPE["CALL-ID"] = ICSSIP_HEADER_CALL_ID
ICSSIP_HEADER_STRING2TYPE["CALL-INFO"] = ICSSIP_HEADER_CALL_INFO
ICSSIP_HEADER_STRING2TYPE["CONTACT"] = ICSSIP_HEADER_CONTACT
ICSSIP_HEADER_STRING2TYPE["CONTENT-DISPOSITION"] = ICSSIP_HEADER_CONTENT_DISPOSITION
ICSSIP_HEADER_STRING2TYPE["CONTENT-ENCODING"] = ICSSIP_HEADER_CONTENT_ENCODING
ICSSIP_HEADER_STRING2TYPE["CONTENT-LANGUAGE"] = ICSSIP_HEADER_CONTENT_LANGUAGE
ICSSIP_HEADER_STRING2TYPE["CONTENT-LENGTH"] = ICSSIP_HEADER_CONTENT_LENGTH
ICSSIP_HEADER_STRING2TYPE["CONTENT-TYPE"] = ICSSIP_HEADER_CONTENT_TYPE
ICSSIP_HEADER_STRING2TYPE["CSEQ"] = ICSSIP_HEADER_CSEQ
ICSSIP_HEADER_STRING2TYPE["DATE"] = ICSSIP_HEADER_DATE
ICSSIP_HEADER_STRING2TYPE["ERROR-INFO"] = ICSSIP_HEADER_ERROR_INFO
ICSSIP_HEADER_STRING2TYPE["EXPIRES"] = ICSSIP_HEADER_EXPIRES
ICSSIP_HEADER_STRING2TYPE["FROM"] = ICSSIP_HEADER_FROM
ICSSIP_HEADER_STRING2TYPE["IN-REPLY-TO"] = ICSSIP_HEADER_IN_REPLY_TO
ICSSIP_HEADER_STRING2TYPE["MAX-FORWARDS"] = ICSSIP_HEADER_MAX_FORWARDS
ICSSIP_HEADER_STRING2TYPE["MIN-EXPIRES"] = ICSSIP_HEADER_MIN_EXPIRES
ICSSIP_HEADER_STRING2TYPE["MIME-VERSION"] = ICSSIP_HEADER_MIME_VERSION
ICSSIP_HEADER_STRING2TYPE["ORGANIZATION"] = ICSSIP_HEADER_ORGANIZATION
ICSSIP_HEADER_STRING2TYPE["PRIORITY"] = ICSSIP_HEADER_PRIORITY
ICSSIP_HEADER_STRING2TYPE["PROXY-AUTHENTICATE"] = ICSSIP_HEADER_PROXY_AUTHENTICATE
ICSSIP_HEADER_STRING2TYPE["PROXY-AUTHORIZATION"] = ICSSIP_HEADER_PROXY_AUTHORIZATION
ICSSIP_HEADER_STRING2TYPE["PROXY-REQUIRE"] = ICSSIP_HEADER_PROXY_REQUIRE
ICSSIP_HEADER_STRING2TYPE["RECORD-ROUTE"] = ICSSIP_HEADER_RECORD_ROUTE
ICSSIP_HEADER_STRING2TYPE["REPLY-TO"] = ICSSIP_HEADER_REPLY_TO
ICSSIP_HEADER_STRING2TYPE["REQUIRE"] = ICSSIP_HEADER_REQUIRE
ICSSIP_HEADER_STRING2TYPE["RETRY-AFTER"] = ICSSIP_HEADER_RETRY_AFTER
ICSSIP_HEADER_STRING2TYPE["ROUTE"] = ICSSIP_HEADER_ROUTE
ICSSIP_HEADER_STRING2TYPE["RACK"] = ICSSIP_HEADER_RACK
ICSSIP_HEADER_STRING2TYPE["RSEQ"] = ICSSIP_HEADER_RSEQ
ICSSIP_HEADER_STRING2TYPE["SERVER"] = ICSSIP_HEADER_SERVER
ICSSIP_HEADER_STRING2TYPE["SUBJECT"] = ICSSIP_HEADER_SUBJECT
ICSSIP_HEADER_STRING2TYPE["SUPPORTED"] = ICSSIP_HEADER_SUPPORTED
ICSSIP_HEADER_STRING2TYPE["TIMESTAMP"] = ICSSIP_HEADER_TIMESTAMP
ICSSIP_HEADER_STRING2TYPE["TO"] = ICSSIP_HEADER_TO
ICSSIP_HEADER_STRING2TYPE["UNSUPPORTED"] = ICSSIP_HEADER_UNSUPPORTED
ICSSIP_HEADER_STRING2TYPE["USER-AGENT"] = ICSSIP_HEADER_USER_AGENT
ICSSIP_HEADER_STRING2TYPE["VIA"] = ICSSIP_HEADER_VIA
ICSSIP_HEADER_STRING2TYPE["WARNING"] = ICSSIP_HEADER_WARNING
ICSSIP_HEADER_STRING2TYPE["WWW-AUTHENTICATE"] = ICSSIP_HEADER_WWW_AUTHENTICATE
}
func initStatusCodeString() {
ICSSIP_STATUSCODE_STRING = make(map[ICSSIP_STATUSCODE_TYPE]string)
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_100] = "100 Trying"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_180] = "180 Ringing"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_181] = "181 Call Is Being Forwarded"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_182] = "182 Queued"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_183] = "183 Session Progress"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_200] = "200 OK"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_300] = "300 Multiple Choices"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_301] = "301 Moved Permanentily"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_302] = "302 Moved Temporarily"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_305] = "305 Use Proxy"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_380] = "380 Alternative Service"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_400] = "400 Bad Request"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_401] = "401 Unauthorized"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_402] = "402 Payment Required"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_403] = "403 Forbidden"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_404] = "404 Not Found"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_405] = "405 Method Not Allowed"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_406] = "406 Not Acceptable"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_407] = "407 Proxy Authentication Required"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_408] = "408 Request Timeout"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_410] = "410 Gone"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_413] = "413 Request Entity Too Large"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_414] = "414 Request-URI Too Long"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_415] = "415 Unsupported Media Type"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_416] = "416 Unsupported URI Scheme"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_420] = "420 Bad Extension"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_421] = "421 Extension Required"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_423] = "423 Interval Too Brief"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_480] = "480 Temporarily Unavailable"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_481] = "481 Call/Transaction Does Not Exist"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_482] = "482 Loop Detected"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_483] = "483 Too Many Hops"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_484] = "484 Address Incomplete"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_485] = "485 Ambiguous"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_486] = "486 Busy Here"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_487] = "487 Request Terminated"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_488] = "488 Not Acceptable Here"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_491] = "491 Request Pending"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_493] = "493 Undecipherable"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_500] = "500 Server Internal Error"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_501] = "501 Not Implemented"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_502] = "502 Bad Gateway"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_503] = "503 Service Unavailable"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_504] = "504 Server Time-out"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_505] = "505 Version Not Supported"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_513] = "513 Message Too Large"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_600] = "600 Busy Everywhere"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_603] = "603 Decline"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_604] = "604 Does Not Exist Anywhere"
ICSSIP_STATUSCODE_STRING[ICSSIP_STATUSCODE_606] = "606 Not Acceptable"
}
func Init() {
}
/*
ICSSIP_METHOD_REGISTER ICSSIP_METHOD_TYPE = iota
ICSSIP_METHOD_ACK
ICSSIP_METHOD_INVITE
ICSSIP_METHOD_BYE
ICSSIP_METHOD_CANCEL
ICSSIP_METHOD_INFO
ICSSIP_METHOD_PRACK
ICSSIP_METHOD_SUBSCRIBE
ICSSIP_METHOD_NOTIFY
ICSSIP_METHOD_PUBLISH
ICSSIP_METHOD_REFER
ICSSIP_METHOD_MESSAGE
ICSSIP_METHOD_UPDATE
ICSSIP_METHOD_OPTIONS
ICSSIP_METHOD_SIP20
*/
/*
Accept
Accept-Encoding
Accept-Language
Alert-Info
Allow
Authentication-Info
Authorization
Call-ID
Call-Info
Contact
Content-Disposition
Content-Encoding
Content-Language
Content-Length
Content-Type
CSeq
Date
Error-Info
Expires
From
In-Reply-To
Max-Forwards
Min-Expires
MIME-Version
Organization
Priority
Proxy-Authenticate
Proxy-Authorization
Proxy-Require
Record-Route
Reply-To
Require
Retry-After
Route
Server
Subject
Supported
Timestamp
To
Unsupported
User-Agent
Via
Warning
WWW-Authenticate
Accept
Accept-Encoding
Accept-Language
Alert-Info
Allow
Authentication-Info
Authorization
Call-ID
Call-Info
Contact
Content-Disposition
Content-Encoding
Content-Language
Content-Length
Content-Type
CSeq
Date
Error-Info
Expires
From
In-Reply-To
Max-Forwards
Min-Expires
MIME-Version
Organization
Priority
Proxy-Authenticate
Proxy-Authorization
Proxy-Require
Record-Route
Reply-To
Require
Retry-After
Route
Server
Subject
Supported
Timestamp
To
Unsupported
User-Agent
Via
Warning
WWW-Authenticate
*/

@ -0,0 +1,4 @@
#!/usr/bin/sh
BIN=$ICSVG_ROOT/bin
msg=`$BIN/loader`
echo $msg

@ -0,0 +1 @@
LD_LIBRARY_PATH=/usr/local/lib /home/shbaik/dev/work/go/bin/dlv debug /home/shbaik/dev/work/voicegateway/voicegateway.go

@ -0,0 +1 @@
sudo LD_LIBRARY_PATH=/usr/local/lib ICSVG_ROOT=/home/icsvg go run /home/shbaik/dev/work/voicegateway/voicegateway.go

@ -0,0 +1 @@
sudo LD_LIBRARY_PATH=/usr/local/lib ICSVG_ROOT=/home/icsvg /home/shbaik/dev/work/voicegateway/voicegateway

@ -0,0 +1,4 @@
#!/usr/bin/sh
HOME=$ICSVG_ROOT
`cat $HOME/voicegateway.pid | xargs kill`
echo "VoiceGateway Stoped..."

@ -0,0 +1,29 @@
package main
import (
"fmt"
"io/ioutil"
"time"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
"gitlab.com/ics_cinnamon/voicegateway/icsrtp"
)
func main() {
alawData, ferr := ioutil.ReadFile("../voice/ohmygirl-dolphin-mono.alaw")
if ferr != nil {
fmt.Println("COULD NOT READ OHMYGIRL'S DOLPHIN!!!", ferr)
return
}
alawDataLen := len(alawData)
fmt.Println("alawDataLen", alawDataLen)
rtp := icsrtp.NewRTP(1,
int(icspacketparser.PCMA),
123,
int(time.Now().Unix()),
0x3d99e5cd,
alawData[:160])
fmt.Printf("%v\nPayload len: %d\n", rtp, len(rtp.Payload))
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

@ -0,0 +1,142 @@
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/voicegateway/icsapp"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
"gitlab.com/ics_cinnamon/voicegateway/icsutil"
)
func main() {
service := icssvc.NewService()
///////////////////////////////////
//Demonize service
//check Voice Gateway pid file - ICSVG_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], "ICSVG_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/icsvg.xml", homeDir)
//configFile := fmt.Sprintf("%s/config/icsvg.xml", service.GetHomeDir())
//fmt.Println("Config file:", configFile)
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 Gateway Home: %s\n", homeDir)
fmt.Printf("iComsys Voice Gateway 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()
*/
}

@ -0,0 +1,93 @@
package main
import (
"fmt"
"os"
"strings"
"time"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icsutil"
)
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], "ICSVG_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/icsvg.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,
)
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/icsvg.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 {
icsLog.Print(icslog.LOG_LEVEL_INFO, -1, "Voice Gateway Death - reloading...")
if lerr != nil {
lerr.PrintWithCaller(0)
}
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)
}
time.Sleep(time.Second * 15)
}
}
Loading…
Cancel
Save