2019-04-16 10:15:44 +03:00
|
|
|
/*
|
|
|
|
NAME
|
|
|
|
client_test.go
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
client_test.go contains testing utilities for functionality provided in client.go.
|
|
|
|
|
|
|
|
AUTHORS
|
|
|
|
Saxon A. Nelson-Milton <saxon@ausocean.org>
|
|
|
|
|
|
|
|
LICENSE
|
|
|
|
This is Copyright (C) 2019 the Australian Ocean Lab (AusOcean)
|
|
|
|
|
|
|
|
It 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
|
|
|
|
in gpl.txt. If not, see http://www.gnu.org/licenses.
|
|
|
|
*/
|
|
|
|
|
2019-04-15 07:31:38 +03:00
|
|
|
package rtcp
|
|
|
|
|
2019-04-15 11:05:36 +03:00
|
|
|
import (
|
|
|
|
"bytes"
|
2019-04-16 06:03:58 +03:00
|
|
|
"encoding/binary"
|
2019-04-15 11:05:36 +03:00
|
|
|
"fmt"
|
|
|
|
"math"
|
2019-04-16 06:03:58 +03:00
|
|
|
"net"
|
|
|
|
"strings"
|
2019-04-15 11:05:36 +03:00
|
|
|
"testing"
|
2019-04-16 06:03:58 +03:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"bitbucket.org/ausocean/utils/logger"
|
2019-04-15 11:05:36 +03:00
|
|
|
)
|
|
|
|
|
2019-04-16 06:03:58 +03:00
|
|
|
// TestFromPayload checks that formPayload is working as expected.
|
2019-04-15 11:05:36 +03:00
|
|
|
func TestFormPayload(t *testing.T) {
|
2019-04-16 10:01:04 +03:00
|
|
|
// Expected data from a valid RTCP packet.
|
2019-04-15 11:05:36 +03:00
|
|
|
expect := []byte{
|
|
|
|
0x81, 0xc9, 0x00, 0x07,
|
|
|
|
0xd6, 0xe0, 0x98, 0xda,
|
|
|
|
0x6f, 0xad, 0x40, 0xc6,
|
|
|
|
0x00, 0xff, 0xff, 0xff,
|
|
|
|
0x00, 0x01, 0x83, 0x08,
|
|
|
|
0x00, 0x00, 0x00, 0x20,
|
|
|
|
0xb9, 0xe1, 0x25, 0x2a,
|
|
|
|
0x00, 0x00, 0x2b, 0xf9,
|
|
|
|
0x81, 0xca, 0x00, 0x04,
|
|
|
|
0xd6, 0xe0, 0x98, 0xda,
|
|
|
|
0x01, 0x08, 0x73, 0x61,
|
|
|
|
0x78, 0x6f, 0x6e, 0x2d,
|
|
|
|
0x70, 0x63, 0x00, 0x00,
|
|
|
|
}
|
|
|
|
|
|
|
|
report := ReceiverReport{
|
|
|
|
Header: Header{
|
|
|
|
Version: 2,
|
|
|
|
Padding: false,
|
|
|
|
ReportCount: 1,
|
|
|
|
Type: typeReceiverReport,
|
|
|
|
},
|
|
|
|
SenderSSRC: 3605043418,
|
|
|
|
Blocks: []ReportBlock{
|
|
|
|
ReportBlock{
|
2019-04-23 08:00:05 +03:00
|
|
|
SourceIdentifier: 1873625286,
|
|
|
|
FractionLost: 0,
|
|
|
|
PacketsLost: math.MaxUint32,
|
|
|
|
HighestSequence: 99080,
|
|
|
|
Jitter: 32,
|
|
|
|
SenderReportTs: 3118540074,
|
|
|
|
SenderReportDelay: 11257,
|
2019-04-15 11:05:36 +03:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Extensions: nil,
|
|
|
|
}
|
|
|
|
|
2019-04-23 08:03:27 +03:00
|
|
|
description := Description{
|
2019-04-15 11:05:36 +03:00
|
|
|
Header: Header{
|
|
|
|
Version: 2,
|
|
|
|
Padding: false,
|
|
|
|
ReportCount: 1,
|
2019-04-23 08:03:27 +03:00
|
|
|
Type: typeDescription,
|
2019-04-15 11:05:36 +03:00
|
|
|
},
|
|
|
|
Chunks: []Chunk{
|
|
|
|
Chunk{
|
|
|
|
SSRC: 3605043418,
|
|
|
|
Items: []SDESItem{
|
|
|
|
SDESItem{
|
|
|
|
Type: typeCName,
|
|
|
|
Text: []byte("saxon-pc"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-04-19 07:45:43 +03:00
|
|
|
c := &Client{}
|
2019-04-15 11:05:36 +03:00
|
|
|
p := c.formPayload(&report, &description)
|
|
|
|
|
|
|
|
if !bytes.Equal(p, expect) {
|
|
|
|
t.Fatalf("unexpected result.\nGot: %v\n Want: %v\n", p, expect)
|
|
|
|
}
|
|
|
|
|
|
|
|
bufAddr := fmt.Sprintf("%p", c.buf[:])
|
|
|
|
pAddr := fmt.Sprintf("%p", p)
|
|
|
|
if bufAddr != pAddr {
|
|
|
|
t.Errorf("unexpected result.\nGot: %v\n want: %v\n", pAddr, bufAddr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-16 06:03:58 +03:00
|
|
|
// dummyLogger will allow logging to be done by the testing pkg.
|
|
|
|
type dummyLogger testing.T
|
|
|
|
|
|
|
|
func (dl *dummyLogger) log(lvl int8, msg string, args ...interface{}) {
|
|
|
|
var l string
|
|
|
|
switch lvl {
|
|
|
|
case logger.Warning:
|
|
|
|
l = "warning"
|
|
|
|
case logger.Debug:
|
|
|
|
l = "debug"
|
|
|
|
case logger.Info:
|
|
|
|
l = "info"
|
|
|
|
case logger.Error:
|
|
|
|
l = "error"
|
|
|
|
case logger.Fatal:
|
|
|
|
l = "fatal"
|
|
|
|
}
|
|
|
|
msg = l + ": " + msg
|
|
|
|
for i := 0; i < len(args); i++ {
|
|
|
|
msg += " %v"
|
|
|
|
}
|
|
|
|
if len(args) == 0 {
|
|
|
|
dl.Log(msg + "\n")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
dl.Logf(msg+"\n", args)
|
2019-04-15 07:31:38 +03:00
|
|
|
}
|
|
|
|
|
2019-04-16 06:03:58 +03:00
|
|
|
// TestReceiveAndSend tests basic RTCP client behaviour with a basic RTCP server.
|
|
|
|
// The RTCP client will send through receiver reports, and the RTCP server will
|
|
|
|
// respond with sender reports.
|
|
|
|
func TestReceiveAndSend(t *testing.T) {
|
|
|
|
const clientAddr, serverAddr = "localhost:8000", "localhost:8001"
|
|
|
|
c, err := NewClient(
|
|
|
|
clientAddr,
|
|
|
|
serverAddr,
|
|
|
|
"testClient",
|
|
|
|
10*time.Millisecond,
|
|
|
|
12345,
|
|
|
|
(*dummyLogger)(t).log,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error when creating client: %v\n", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
2019-04-23 06:56:56 +03:00
|
|
|
case err := <-c.Err():
|
2019-04-16 06:03:58 +03:00
|
|
|
const errConnClosed = "use of closed network connection"
|
|
|
|
if !strings.Contains(err.Error(), errConnClosed) {
|
|
|
|
t.Fatalf("error received from client error chan: %v\n", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
c.Start()
|
|
|
|
|
|
|
|
sAddr, err := net.ResolveUDPAddr("udp", serverAddr)
|
2019-04-15 07:31:38 +03:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("could not resolve test server address, failed with error: %v", err)
|
|
|
|
}
|
|
|
|
|
2019-04-16 06:03:58 +03:00
|
|
|
cAddr, err := net.ResolveUDPAddr("udp", clientAddr)
|
2019-04-15 07:31:38 +03:00
|
|
|
if err != nil {
|
2019-04-16 06:03:58 +03:00
|
|
|
t.Fatalf("could not resolve client address, failed with error: %v", err)
|
2019-04-15 07:31:38 +03:00
|
|
|
}
|
|
|
|
|
2019-04-16 06:03:58 +03:00
|
|
|
conn, err := net.DialUDP("udp", sAddr, cAddr)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("could not dial, failed with error: %v\n", err)
|
2019-04-15 07:31:38 +03:00
|
|
|
}
|
2019-04-15 11:05:36 +03:00
|
|
|
|
2019-04-16 06:03:58 +03:00
|
|
|
buf := make([]byte, 4096)
|
|
|
|
for i := 0; i < 5; i++ {
|
|
|
|
t.Log("SERVER: waiting for receiver report\n")
|
|
|
|
n, _, _ := conn.ReadFromUDP(buf)
|
|
|
|
t.Logf("SERVER: receiver report received: \n%v\n", buf[:n])
|
|
|
|
|
2019-04-19 07:45:43 +03:00
|
|
|
c.SetSequence(uint32(i))
|
2019-04-16 06:03:58 +03:00
|
|
|
|
|
|
|
now := time.Now().Second()
|
|
|
|
var time [8]byte
|
|
|
|
binary.BigEndian.PutUint64(time[:], uint64(now))
|
2019-04-16 10:46:13 +03:00
|
|
|
msw := binary.BigEndian.Uint32(time[:4])
|
2019-04-16 06:03:58 +03:00
|
|
|
lsw := binary.BigEndian.Uint32(time[4:])
|
|
|
|
|
|
|
|
report := SenderReport{
|
|
|
|
Header: Header{
|
2019-04-16 10:46:13 +03:00
|
|
|
Version: rtcpVer,
|
2019-04-16 06:03:58 +03:00
|
|
|
Padding: false,
|
|
|
|
ReportCount: 0,
|
|
|
|
Type: typeSenderReport,
|
|
|
|
},
|
|
|
|
SSRC: 1234567,
|
|
|
|
TimestampMSW: msw,
|
|
|
|
TimestampLSW: lsw,
|
|
|
|
RTPTimestamp: 0,
|
|
|
|
PacketCount: 0,
|
|
|
|
OctetCount: 0,
|
|
|
|
}
|
|
|
|
r := report.Bytes()
|
|
|
|
t.Logf("SERVER: sending sender report: \n%v\n", r)
|
|
|
|
_, err := conn.Write(r)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("did not expect error: %v\n", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c.Stop()
|
|
|
|
}
|