From e65559104628969141b713695242ff281e0918b7 Mon Sep 17 00:00:00 2001 From: ffmiyo Date: Wed, 3 Feb 2021 22:00:23 +0800 Subject: [PATCH] Implement packet clone method Clone performs deep copy on a packet to produce equivalent but independently mutable packet. Fixes #88 --- packet.go | 33 +++++++++++++++++++++++++++++++ packet_test.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/packet.go b/packet.go index f1f12a6..26a087e 100644 --- a/packet.go +++ b/packet.go @@ -507,3 +507,36 @@ func (p Packet) MarshalTo(buf []byte) (n int, err error) { func (p Packet) MarshalSize() int { return p.Header.MarshalSize() + len(p.Payload) + int(p.PaddingSize) } + +// Clone returns a deep copy of p. +func (p Packet) Clone() *Packet { + clone := &Packet{} + clone.Header = p.Header.Clone() + if p.Payload != nil { + clone.Payload = make([]byte, len(p.Payload)) + copy(clone.Payload, p.Payload) + } + clone.PaddingSize = p.PaddingSize + return clone +} + +// Clone returns a deep copy h. +func (h Header) Clone() Header { + clone := h + if h.CSRC != nil { + clone.CSRC = make([]uint32, len(h.CSRC)) + copy(clone.CSRC, h.CSRC) + } + if h.Extensions != nil { + ext := make([]Extension, len(h.Extensions)) + for i, e := range h.Extensions { + ext[i] = e + if e.payload != nil { + ext[i].payload = make([]byte, len(e.payload)) + copy(ext[i].payload, e.payload) + } + } + clone.Extensions = ext + } + return clone +} diff --git a/packet_test.go b/packet_test.go index 0ccd26c..40cb1a0 100644 --- a/packet_test.go +++ b/packet_test.go @@ -1390,6 +1390,59 @@ func TestRoundtrip(t *testing.T) { } } +func TestCloneHeader(t *testing.T) { + h := Header{ + Marker: true, + Extension: true, + ExtensionProfile: 1, + Extensions: []Extension{ + {0, []byte{ + 0xFF, 0xFF, 0xFF, 0xFF, + }}, + }, + Version: 2, + PayloadType: 96, + SequenceNumber: 27023, + Timestamp: 3653407706, + SSRC: 476325762, + CSRC: []uint32{}, + } + clone := h.Clone() + if !reflect.DeepEqual(h, clone) { + t.Errorf("Cloned clone does not match the original") + } + + h.CSRC = append(h.CSRC, 1) + if len(clone.CSRC) == len(h.CSRC) { + t.Errorf("Expected CSRC to be unchanged") + } + h.Extensions[0].payload[0] = 0x1F + if clone.Extensions[0].payload[0] == 0x1F { + t.Errorf("Expected Extensions to be unchanged") + } +} + +func TestClonePacket(t *testing.T) { + rawPkt := []byte{ + 0x90, 0xe0, 0x69, 0x8f, 0xd9, 0xc2, 0x93, 0xda, 0x1c, 0x64, + 0x27, 0x82, 0xBE, 0xDE, 0x00, 0x01, 0x50, 0xAA, 0x00, 0x00, + 0x98, 0x36, 0xbe, 0x88, 0x9e, + } + p := &Packet{ + Payload: rawPkt[20:], + } + + clone := p.Clone() + if !reflect.DeepEqual(p, clone) { + t.Errorf("Cloned Packet does not match the original") + } + + p.Payload[0] = 0x1F + if clone.Payload[0] == 0x1F { + t.Errorf("Expected Payload to be unchanged") + } +} + func BenchmarkMarshal(b *testing.B) { rawPkt := []byte{ 0x90, 0x60, 0x69, 0x8f, 0xd9, 0xc2, 0x93, 0xda, 0x1c, 0x64,