first init
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] & 1 != 1 && udp[3] & 1 != 1 && udp[8] & 0x80 == 0x80 && length < 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
|
||||
}
|
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]
|
||||
}
|
Binary file not shown.
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))
|
||||
}
|
Binary file not shown.
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…
Reference in New Issue