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.

133 lines
2.6 KiB
Go

/*
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)
}