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 // 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. // reports to the server.
func (c *client) Start() { func (c *client) Start() {
go c.listen() go c.listen()
go c.send() 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() { func (c *client) listen() {
conn, err := net.ListenUDP("udp", c.cAddr) conn, err := net.ListenUDP("udp", c.cAddr)
if err != nil { 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() { func (c *client) send() {
conn, err := net.DialUDP("udp", c.cAddr, c.sAddr) conn, err := net.DialUDP("udp", c.cAddr, c.sAddr)
if err != nil { if err != nil {
@ -154,12 +154,15 @@ func (c *client) parse(buf []byte) {
c.setSenderTs(msw, lsw) c.setSenderTs(msw, lsw)
} }
// UpdateSequence will allow updating of the highest sequence number received
// through an rtp stream.
func (c *client) UpdateSequence(s uint32) { func (c *client) UpdateSequence(s uint32) {
c.mu.Lock() c.mu.Lock()
c.sequence = s c.sequence = s
c.mu.Unlock() c.mu.Unlock()
} }
// highestSequence will return the highest sequence number received through rtp.
func (c *client) highestSequence() uint32 { func (c *client) highestSequence() uint32 {
var s uint32 var s uint32
c.mu.Lock() c.mu.Lock()
@ -168,10 +171,13 @@ func (c *client) highestSequence() uint32 {
return s return s
} }
// jitter returns the interarrival jitter as described by RTCP specifications:
// https://tools.ietf.org/html/rfc3550
func (c *client) jitter() uint32 { func (c *client) jitter() uint32 {
return 0 return 0
} }
// setSenderTs allows us to safely set the current sender report timestamp.
func (c *client) setSenderTs(msw, lsw uint32) { func (c *client) setSenderTs(msw, lsw uint32) {
c.mu.Lock() c.mu.Lock()
binary.BigEndian.PutUint32(c.senderTs[:], msw) binary.BigEndian.PutUint32(c.senderTs[:], msw)
@ -179,6 +185,7 @@ func (c *client) setSenderTs(msw, lsw uint32) {
c.mu.Unlock() c.mu.Unlock()
} }
// lastSenderTs returns the timestamp of the most recent sender report.
func (c *client) lastSenderTs() uint32 { func (c *client) lastSenderTs() uint32 {
var ts uint32 var ts uint32
c.mu.Lock() c.mu.Lock()
@ -187,6 +194,8 @@ func (c *client) lastSenderTs() uint32 {
return ts 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 { func (c *client) delay() uint32 {
var receiveTime time.Time var receiveTime time.Time
c.mu.Lock() c.mu.Lock()
@ -196,6 +205,7 @@ func (c *client) delay() uint32 {
return uint32(now.Sub(receiveTime).Seconds() / delayUnit) 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() { func (c *client) received() {
c.mu.Lock() c.mu.Lock()
c.receiveTime = time.Now() 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 // 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 // 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) { func Timestamp(buf []byte) (msw, lsw uint32, err error) {
// First check version of rtcp
if (buf[0] & 0xc0 >> 6) != 2 { if (buf[0] & 0xc0 >> 6) != 2 {
return 0, 0, errors.New("incompatible RTCP version") return 0, 0, errors.New("incompatible RTCP version")
} }
// Check type of packet
if buf[1] != typeSenderReport { if buf[1] != typeSenderReport {
return 0, 0, errors.New("rtcp packet is not of sender report type") return 0, 0, errors.New("rtcp packet is not of sender report type")
} }

View File

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

View File

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