protocol/rtcp: addressing PR feedback

This commit is contained in:
Saxon 2019-04-19 14:15:43 +09:30
parent d34eabcd34
commit a8e56311c2
3 changed files with 62 additions and 55 deletions

View File

@ -1,9 +1,9 @@
/* /*
NAME NAME
client.go Client.go
DESCRIPTION DESCRIPTION
client.go provides an implemntation of a basic RTCP client that will send Client.go provides an implemntation of a basic RTCP Client that will send
receiver reports, and receive sender reports to parse relevant statistics. receiver reports, and receive sender reports to parse relevant statistics.
AUTHORS AUTHORS
@ -41,44 +41,45 @@ import (
) )
const ( const (
senderSSRC = 3605043418 senderSSRC = 1 // Any non-zero value will do.
defaultClientName = "client" defaultClientName = "Client"
delayUnit = 1.0 / 65536.0 delayUnit = 1.0 / 65536.0
pkg = "rtcp: " pkg = "rtcp: "
rtcpVer = 2 rtcpVer = 2
receiverBufSize = 200
) )
type log func(lvl int8, msg string, args ...interface{}) type log func(lvl int8, msg string, args ...interface{})
// client is an RTCP client that will hadle receiving SenderReports from a server // Client is an RTCP Client that will handle receiving SenderReports from a server
// and sending out ReceiverReports. // and sending out ReceiverReports.
type client struct { type Client struct {
ErrChan chan error ErrChan chan error // Client will send any errors through this chan.
cAddr *net.UDPAddr cAddr *net.UDPAddr // Address of client.
sAddr *net.UDPAddr sAddr *net.UDPAddr // Address of RTSP server.
name string name string // Name of the client for source description purposes.
sourceSSRC uint32 sourceSSRC uint32 // Source identifier of this client.
mu sync.Mutex mu sync.Mutex // Will be used to change parameters during operation safely.
sequence uint32 sequence uint32 // Last RTP sequence number.
senderTs [64]byte senderTs [8]byte // The timestamp of the last sender report.
interval time.Duration interval time.Duration // Interval between sender report and receiver report.
receiveTime time.Time receiveTime time.Time // Time last sender report was received.
buf [200]byte buf [receiverBufSize]byte // Buf used to store the receiver report and source descriptions.
conn *net.UDPConn conn *net.UDPConn // The UDP connection used for receiving and sending RTSP packets.
wg sync.WaitGroup wg sync.WaitGroup // This is used to wait for send and recv routines to stop when Client is stopped.
quitSend chan struct{} quitSend chan struct{} // Channel used to communicate quit signal to send routine.
quitRecv chan struct{} quitRecv chan struct{} // Channel used to communicate quit signal to recv routine.
log log // Used to log any messages.
} }
// NewClient returns a pointer to a new client. // NewClient returns a pointer to a new Client.
func NewClient(clientAddress, serverAddress, name string, sendInterval time.Duration, rtpSSRC uint32, l log) (*client, error) { func NewClient(clientAddress, serverAddress, name string, sendInterval time.Duration, rtpSSRC uint32, l log) (*Client, error) {
if name == "" { if name == "" {
name = defaultClientName name = defaultClientName
} }
c := &client{ c := &Client{
name: name, name: name,
ErrChan: make(chan error, 2), ErrChan: make(chan error, 2),
quitSend: make(chan struct{}), quitSend: make(chan struct{}),
@ -91,7 +92,7 @@ func NewClient(clientAddress, serverAddress, name string, sendInterval time.Dura
var err error var err error
c.cAddr, err = net.ResolveUDPAddr("udp", clientAddress) c.cAddr, err = net.ResolveUDPAddr("udp", clientAddress)
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprintf("can't resolve client address, failed with error: %v\n", err)) return nil, errors.New(fmt.Sprintf("can't resolve Client address, failed with error: %v\n", err))
} }
c.sAddr, err = net.ResolveUDPAddr("udp", serverAddress) c.sAddr, err = net.ResolveUDPAddr("udp", serverAddress)
@ -109,18 +110,17 @@ 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 sender reports, 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() {
c.log(logger.Debug, pkg+"client is starting") c.log(logger.Debug, pkg+"Client is starting")
c.wg.Add(1) c.wg.Add(2)
go c.recv() go c.recv()
c.wg.Add(1)
go c.send() go c.send()
} }
// Stop sends a quit signal to the send and receive routines and closes the // Stop sends a quit signal to the send and receive routines and closes the
// UDP connection. It will wait until both routines have returned. // UDP connection. It will wait until both routines have returned.
func (c *client) Stop() { func (c *Client) Stop() {
c.log(logger.Debug, pkg+"client is stopping") c.log(logger.Debug, pkg+"Client is stopping")
close(c.quitSend) close(c.quitSend)
close(c.quitRecv) close(c.quitRecv)
c.conn.Close() c.conn.Close()
@ -128,9 +128,9 @@ func (c *client) Stop() {
} }
// recv reads from the UDP connection and parses SenderReports. // recv reads from the UDP connection and parses SenderReports.
func (c *client) recv() { func (c *Client) recv() {
defer c.wg.Done() defer c.wg.Done()
c.log(logger.Debug, pkg+"client is receiving") c.log(logger.Debug, pkg+"Client is receiving")
buf := make([]byte, 4096) buf := make([]byte, 4096)
for { for {
select { select {
@ -149,9 +149,9 @@ func (c *client) recv() {
} }
// send writes receiver reports to the server. // send writes receiver reports to the server.
func (c *client) send() { func (c *Client) send() {
defer c.wg.Done() defer c.wg.Done()
c.log(logger.Debug, pkg+"client is sending") c.log(logger.Debug, pkg+"Client is sending")
for { for {
select { select {
case <-c.quitSend: case <-c.quitSend:
@ -211,38 +211,45 @@ func (c *client) send() {
} }
// formPayload takes a pointer to a ReceiverReport and a pointer to a // formPayload takes a pointer to a ReceiverReport and a pointer to a
// Source Description and calls Bytes on both, writing to the underlying client // Source Description and calls Bytes on both, writing to the underlying Client
// buf. A slice to the combined writtem memory is returned. // buf. A slice to the combined writtem memory is returned.
func (c *client) formPayload(r *ReceiverReport, d *SourceDescription) []byte { func (c *Client) formPayload(r *ReceiverReport, d *SourceDescription) []byte {
rl := len(r.Bytes(c.buf[:])) rl := len(r.Bytes(c.buf[:]))
dl := len(d.Bytes(c.buf[rl:])) dl := len(d.Bytes(c.buf[rl:]))
t := rl + dl t := rl + dl
if t > cap(c.buf) { if t > cap(c.buf) {
panic("client buf not big enough") panic("Client buf not big enough")
} }
return c.buf[:t] return c.buf[:t]
} }
// parse will read important statistics from sender reports. // parse will read important statistics from sender reports.
func (c *client) parse(buf []byte) { func (c *Client) parse(buf []byte) {
c.received() c.markReceivedTime()
msw, lsw, err := Timestamp(buf) msw, lsw, err := Timestamp(buf)
if err != nil { if err != nil {
c.ErrChan <- errors.New(fmt.Sprintf("could not get timestamp from sender report, failed with error: %v", err)) c.ErrChan <- errors.New(fmt.Sprintf("could not get timestamp from sender report, failed with error: %v", err))
} }
c.setSenderTs(msw, lsw) c.setSenderTs(
struct {
msw uint32
lsw uint32
}{
msw,
lsw,
})
} }
// UpdateSequence will allow updating of the highest sequence number received // SetSequence will allow updating of the highest sequence number received
// through an RTP stream. // through an RTP stream.
func (c *client) UpdateSequence(s uint32) { func (c *Client) SetSequence(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. // highestSequence will return the highest sequence number received through RTP.
func (c *client) highestSequence() uint32 { func (c *Client) highestSequence() uint32 {
c.mu.Lock() c.mu.Lock()
s := c.sequence s := c.sequence
c.mu.Unlock() c.mu.Unlock()
@ -251,20 +258,20 @@ func (c *client) highestSequence() uint32 {
// jitter returns the interarrival jitter as described by RTCP specifications: // jitter returns the interarrival jitter as described by RTCP specifications:
// https://tools.ietf.org/html/rfc3550 // 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. // setSenderTs allows us to safely set the current sender report timestamp.
func (c *client) setSenderTs(msw, lsw uint32) { func (c *Client) setSenderTs(t struct{ msw, lsw uint32 }) {
c.mu.Lock() c.mu.Lock()
binary.BigEndian.PutUint32(c.senderTs[:], msw) binary.BigEndian.PutUint32(c.senderTs[:], t.msw)
binary.BigEndian.PutUint32(c.senderTs[4:], lsw) binary.BigEndian.PutUint32(c.senderTs[4:], t.lsw)
c.mu.Unlock() c.mu.Unlock()
} }
// lastSenderTs returns the timestamp of the most recent sender report. // lastSenderTs returns the timestamp of the most recent sender report.
func (c *client) lastSenderTs() uint32 { func (c *Client) lastSenderTs() uint32 {
c.mu.Lock() c.mu.Lock()
t := binary.BigEndian.Uint32(c.senderTs[2:]) t := binary.BigEndian.Uint32(c.senderTs[2:])
c.mu.Unlock() c.mu.Unlock()
@ -273,7 +280,7 @@ func (c *client) lastSenderTs() uint32 {
// delay returns the duration between the receive time of the last sender report // delay returns the duration between the receive time of the last sender report
// and now. This is called when forming a receiver report. // and now. This is called when forming a receiver report.
func (c *client) delay() uint32 { func (c *Client) delay() uint32 {
c.mu.Lock() c.mu.Lock()
t := c.receiveTime t := c.receiveTime
c.mu.Unlock() c.mu.Unlock()
@ -281,7 +288,7 @@ func (c *client) delay() uint32 {
} }
// received is called when a sender report is received to mark the receive time. // received is called when a sender report is received to mark the receive time.
func (c *client) received() { func (c *Client) markReceivedTime() {
c.mu.Lock() c.mu.Lock()
c.receiveTime = time.Now() c.receiveTime = time.Now()
c.mu.Unlock() c.mu.Unlock()

View File

@ -101,7 +101,7 @@ func TestFormPayload(t *testing.T) {
}, },
} }
c := &client{} c := &Client{}
p := c.formPayload(&report, &description) p := c.formPayload(&report, &description)
if !bytes.Equal(p, expect) { if !bytes.Equal(p, expect) {
@ -197,7 +197,7 @@ func TestReceiveAndSend(t *testing.T) {
n, _, _ := conn.ReadFromUDP(buf) n, _, _ := conn.ReadFromUDP(buf)
t.Logf("SERVER: receiver report received: \n%v\n", buf[:n]) t.Logf("SERVER: receiver report received: \n%v\n", buf[:n])
c.UpdateSequence(uint32(i)) c.SetSequence(uint32(i))
now := time.Now().Second() now := time.Now().Second()
var time [8]byte var time [8]byte

View File

@ -138,7 +138,7 @@ func (d *SourceDescription) Bytes(buf []byte) []byte {
// bodyLen calculates the body length of a source description packet in bytes. // bodyLen calculates the body length of a source description packet in bytes.
func (d *SourceDescription) bodyLen() int { func (d *SourceDescription) bodyLen() int {
l := 0 var l int
for _, c := range d.Chunks { for _, c := range d.Chunks {
l += c.len() l += c.len()
} }