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
133 lines
2.6 KiB
Go
3 years ago
|
/*
|
||
|
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)
|
||
|
}
|