/* RFC 3550. RTP: A Transport Protocol for Real-Time Applications */ package icspacketparser import ( "encoding/binary" "fmt" "gitlab.com/cinnamon/voiceagent/icserror" "gitlab.com/cinnamon/voiceagent/icsnet" ) type RTP struct { Version int 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 const ( PCMU = 0 PCMA = 8 G729 = 18 ) 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) //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) }