You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
3.9 KiB
Go
231 lines
3.9 KiB
Go
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
|
|
}
|