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

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
}