protocol/rtsp: more commenting and started writing client_test.go to check the behaviour of the rtcp client

This commit is contained in:
Saxon 2019-04-15 14:01:38 +09:30
parent 5fa0969530
commit af664b0661
5 changed files with 71 additions and 18 deletions

View File

@ -59,14 +59,14 @@ func NewClient(clientAddress, serverAddress, name string, sendInterval time.Dura
}
// Start starts the listen and send routines. This will start the process of
// receiving and parsing SenderReports, and the process of sending receiver
// receiving and parsing sender reports, and the process of sending receiver
// reports to the server.
func (c *client) Start() {
go c.listen()
go c.send()
}
// Listen reads from the UDP connection and parses SenderReports.
// listen reads from the UDP connection and parses SenderReports.
func (c *client) listen() {
conn, err := net.ListenUDP("udp", c.cAddr)
if err != nil {
@ -79,7 +79,7 @@ func (c *client) listen() {
}
}
// send write sender reports to the server.
// send writes receiver reports to the server.
func (c *client) send() {
conn, err := net.DialUDP("udp", c.cAddr, c.sAddr)
if err != nil {
@ -154,12 +154,15 @@ func (c *client) parse(buf []byte) {
c.setSenderTs(msw, lsw)
}
// UpdateSequence will allow updating of the highest sequence number received
// through an rtp stream.
func (c *client) UpdateSequence(s uint32) {
c.mu.Lock()
c.sequence = s
c.mu.Unlock()
}
// highestSequence will return the highest sequence number received through rtp.
func (c *client) highestSequence() uint32 {
var s uint32
c.mu.Lock()
@ -168,10 +171,13 @@ func (c *client) highestSequence() uint32 {
return s
}
// jitter returns the interarrival jitter as described by RTCP specifications:
// https://tools.ietf.org/html/rfc3550
func (c *client) jitter() uint32 {
return 0
}
// setSenderTs allows us to safely set the current sender report timestamp.
func (c *client) setSenderTs(msw, lsw uint32) {
c.mu.Lock()
binary.BigEndian.PutUint32(c.senderTs[:], msw)
@ -179,6 +185,7 @@ func (c *client) setSenderTs(msw, lsw uint32) {
c.mu.Unlock()
}
// lastSenderTs returns the timestamp of the most recent sender report.
func (c *client) lastSenderTs() uint32 {
var ts uint32
c.mu.Lock()
@ -187,6 +194,8 @@ func (c *client) lastSenderTs() uint32 {
return ts
}
// delay returns the duration between the receive time of the last sender report
// and now. This is called when forming a receiver report.
func (c *client) delay() uint32 {
var receiveTime time.Time
c.mu.Lock()
@ -196,6 +205,7 @@ func (c *client) delay() uint32 {
return uint32(now.Sub(receiveTime).Seconds() / delayUnit)
}
// received is called when a sender report is received to mark the receive time.
func (c *client) received() {
c.mu.Lock()
c.receiveTime = time.Now()

View File

@ -0,0 +1,30 @@
package rtcp
import (
"net"
"testing"
)
func TestReceiveAndSend(t *testing.T) {
quit := make(chan struct{})
go testServer(quit)
}
func testServer(quit chan struct{}, t *testing.T) {
const testServerAddr = "localhost:8000"
sAddr, err := net.ResolveUDPAddr("udp", testServerAddr)
if err != nil {
t.Fatalf("could not resolve test server address, failed with error: %v", err)
}
conn, err := net.DialUDP("udp", nil, sAddr)
if err != nil {
t.Fatalf("could not dial, failed with error: %v", err)
}
select {
case <-quit:
return
default:
}
}

View File

@ -7,14 +7,12 @@ import (
// Timestamp gets the timestamp from a receiver report and returns as the most
// significant word, and the least significant word. If the given bytes do not
// represent a valid receiver report, and error is returned.
// represent a valid receiver report, an error is returned.
func Timestamp(buf []byte) (msw, lsw uint32, err error) {
// First check version of rtcp
if (buf[0] & 0xc0 >> 6) != 2 {
return 0, 0, errors.New("incompatible RTCP version")
}
// Check type of packet
if buf[1] != typeSenderReport {
return 0, 0, errors.New("rtcp packet is not of sender report type")
}

View File

@ -16,18 +16,20 @@ const (
typeCName = 1
)
// MISC.
const (
reportBlockSize = 6
)
// ReceiverReport describes an RTCP receiver report packet.
type ReceiverReport struct {
Header
SenderSSRC uint32
Blocks []ReportBlock
Extensions [][4]byte
Header // Standard RTCP packet header.
SenderSSRC uint32 // SSRC of the sender of this report.
Blocks []ReportBlock // Report blocks.
Extensions [][4]byte // Contains any extensions to the packet.
}
// Bytes returns a []byte of the ReceiverReport r.
func (r *ReceiverReport) Bytes() []byte {
l := 8 + 4*reportBlockSize*len(r.Blocks) + 4*len(r.Extensions)
buf := make([]byte, l)
@ -61,6 +63,7 @@ func (r *ReceiverReport) Bytes() []byte {
return buf
}
// ReportBlock describes an RTCP report block used in Sender/Receiver Reports.
type ReportBlock struct {
SSRC uint32 // Source identifier.
FractionLost uint8 // Fraction of packets lost.
@ -71,12 +74,13 @@ type ReportBlock struct {
DLSR uint32 // Delay since last sender report.
}
// SourceDescription describes a source description RTCP packet.
type SourceDescription struct {
Header
Chunks []Chunk
Header // Standard RTCP packet header.
Chunks []Chunk // Chunks to describe items of each SSRC.
}
// Bytes returns an []byte of the SourceDescription d.
func (d *SourceDescription) Bytes() []byte {
bodyLen := d.bodyLen()
rem := bodyLen % 4
@ -102,6 +106,7 @@ func (d *SourceDescription) Bytes() []byte {
return buf
}
// bodyLen calculates the body length of a source description packet in bytes.
func (d *SourceDescription) bodyLen() int {
l := 0
for _, c := range d.Chunks {
@ -110,6 +115,7 @@ func (d *SourceDescription) bodyLen() int {
return l
}
// Header describes a standard RTCP packet header.
type Header struct {
Version uint8 // RTCP version.
Padding bool // Padding indicator.
@ -117,16 +123,19 @@ type Header struct {
Type uint8 // Type of RTCP packet.
}
// SDESItem describes a source description item.
type SDESItem struct {
Type uint8
Text []byte
Type uint8 // Type of item.
Text []byte // Item text.
}
// Chunk describes a source description chunk for a given SSRC.
type Chunk struct {
SSRC uint32
Items []SDESItem
SSRC uint32 // SSRC of the source being described by the below items.
Items []SDESItem // Items describing the source.
}
// len returns the len of a chunk in bytes.
func (c *Chunk) len() int {
tot := 4
for _, i := range c.Items {
@ -135,6 +144,8 @@ func (c *Chunk) len() int {
return tot
}
// writeHeader writes the standard RTCP header given a buffer to write to and l
// the RTCP body length that needs to be encoded into the header.
func (h Header) writeHeader(buf []byte, l int) {
buf[0] = h.Version<<6 | asByte(h.Padding)<<5 | 0x1f&h.ReportCount
buf[1] = h.Type

View File

@ -6,6 +6,8 @@ import (
"testing"
)
// TestReceiverReportBytes checks that we can correctly obtain a []byte of an
// RTCP receiver report from the struct representation.
func TestReceiverReportBytes(t *testing.T) {
expect := []byte{
0x81, 0xc9, 0x00, 0x07,
@ -48,6 +50,8 @@ func TestReceiverReportBytes(t *testing.T) {
}
}
// TestSourceDescriptionBytes checks that we can correctly obtain a []byte of an
// RTCP source description from the struct representation.
func TestSourceDescriptionBytes(t *testing.T) {
expect := []byte{
0x81, 0xca, 0x00, 0x04,