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 }