protocol/rtp: added parse.go file with parsing functionality

Added parse.go. This file contains functionality to obtain the Payload from an RTP packet.
Unexported functions to help with this extraction have been added; extHeaderLen, hasExt,
csrcCount and version.
This commit is contained in:
Saxon 2019-04-05 14:29:04 +10:30
parent 4978db2f2b
commit af9a9bc6c0
2 changed files with 93 additions and 4 deletions

88
protocol/rtp/parse.go Normal file
View File

@ -0,0 +1,88 @@
/*
NAME
parse.go
DESCRIPTION
parse.go provides functionality for parsing RTP packets.
AUTHOR
Saxon A. Nelson-Milton <saxon@ausocean.org>
LICENSE
Copyright (C) 2019 the Australian Ocean Lab (AusOcean)
This is free software: you can redistribute it and/or modify them
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with revid in gpl.txt. If not, see [GNU licenses](http://www.gnu.org/licenses).
*/
package rtp
import (
"encoding/binary"
"errors"
)
const badVer = "incompatible RTP version"
// Payload returns the payload from an RTP packet provided the version is
// compatible, otherwise an error is returned.
func Payload(d []byte) ([]byte, error) {
if version(d) != rtpVer {
return nil, errors.New(badVer)
}
extLen := 0
if hasExt(d) {
extLen = 4 + 4*extHeaderLen(d)
}
payloadIdx := optionalFieldIdx + 4*csrcCount(d) + extLen
return d[payloadIdx:], nil
}
// extHeaderLen returns the extension header length. The RTP packet must have
// a compatible version, and must have an extension field, otherwise we panic.
func extHeaderLen(d []byte) int {
if version(d) != rtpVer {
panic(badVer)
}
if !hasExt(d) {
panic("RTP packet does not have extension")
}
extIdx := optionalFieldIdx + 4*csrcCount(d)
return int(binary.BigEndian.Uint16(d[extIdx+2 : extIdx+4]))
}
// hasExt returns true if an extension is present in the RTP packet. The version
// must be compatible otherwise we panic.
func hasExt(d []byte) bool {
if version(d) != rtpVer {
panic(badVer)
}
if (d[0] & 0x10 >> 4) == 1 {
return true
}
return false
}
// csrcCount returns the number of CSRC fields. If the version is not compatible
// we panic.
func csrcCount(d []byte) int {
if version(d) != rtpVer {
panic(badVer)
}
return int(d[0] & 0x0f)
}
// version returns the version of the RTP packet.
func version(d []byte) int {
return int(d[0] & 0xb0 >> 4)
}

View File

@ -37,10 +37,11 @@ import (
)
const (
rtpVer = 2
defaultHeadSize = 3 * 4 // Header size of an rtp packet.
defPayloadSize = sendSize // Default payload size for the rtp packet.
defPktSize = defaultHeadSize + defPayloadSize // Default packet size is header size + payload size.
rtpVer = 2
defaultHeadSize = 3 * 4 // Header size of an rtp packet.
defPayloadSize = sendSize // Default payload size for the rtp packet.
defPktSize = defaultHeadSize + defPayloadSize // Default packet size is header size + payload size.
optionalFieldIdx = 12 // This is the idx of optional fields including CSRC and extension header in an RTP packet.
)
// Pkt provides fields consistent with RFC3550 definition of an rtp packet