Skip to content

Commit

Permalink
bug: added missing values to SerializeTo
Browse files Browse the repository at this point in the history
  • Loading branch information
littleairmada committed Jul 10, 2023
1 parent 6b1b205 commit 51da174
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 37 deletions.
98 changes: 68 additions & 30 deletions vrt.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package vrt
import (
"encoding/binary"
"fmt"
"math"

"github.com/google/gopacket"
"github.com/google/gopacket/layers"
Expand Down Expand Up @@ -171,30 +170,29 @@ func (v VRT) LayerContents() (data []byte) {
return []byte(buf.Bytes())
}

// LayerPayload returns the VRT object's Payload
// VRT packets carry a data payload so the Payload byte slice is retured.
func (v VRT) LayerPayload() []byte {
return v.Payload
}

// CanDecode returns a set of layers that VRT objects can decode.
// As VRT objects can only decide the VRT layer, we can return just that layer.
// Apparently a single layer type implements LayerClass.
func (v VRT) CanDecode() gopacket.LayerClass {
func (v *VRT) CanDecode() gopacket.LayerClass {
return LayerTypeVRT
}

// NextLayerType specifies the next layer that GoPacket should attempt to
// analyse after this (VRT) layer. As VRT packets contain payload
// bytes, there is an additional layer to analyse.
func (v VRT) NextLayerType() gopacket.LayerType {
func (v *VRT) NextLayerType() gopacket.LayerType {
return gopacket.LayerTypePayload
}

// LayerPayload returns the VRT object's Payload
// VRT packets carry a data payload so the Payload byte slice is retured.
func (v *VRT) LayerPayload() []byte {
return v.Payload
}

// ValidateVrtPacketSize calculates the minimum size of the VRT packet based on the VRT header
// and compares to the size of the VRT packet. VRT packets below the minimum size through an error.
// header.PacketSize is the number of 32 bit words per packet and should always equal size/4.
// FIXME: fix calculations for packet_words vs packet bytes
func ValidateVrtPacketSize(header Header, size uint32) (outputHeaderSize uint16, ouputMinimumWords uint32, err error) {
var minimumWords uint32 = 1

Expand Down Expand Up @@ -339,22 +337,39 @@ func (v *VRT) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (v *VRT) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
data, err := b.PrependBytes(vrtMinimumRecordSizeInBytes)
size := 4
if (v.Header.Type == IFDataWithStream) || (v.Header.Type == ExtDataWithStream) {
size += 4
}
if v.Header.C {
size += 8
}
if v.Header.TSI != TSINone {
size += 4
}
if v.Header.TSF != TSFNone {
size += 8
}
if v.Header.T {
size += 4
}

data, err := b.PrependBytes(size)
if err != nil {
return err
}

var offset uint32 = 0

// Pack the first few fields into the first 32 bits.
h := uint8(0)
h |= (uint8(v.Header.Type) << 4) & 0xF0
if v.Header.C {
h |= (uint8(1) << 3) & 0x08
}
// h |= (uint8(v.Header.C) << 3) & 0x08
if v.Header.T {
h |= (uint8(1) << 2) & 0x04
}
//h |= (uint8(v.Header.T) << 2) & 0x04
//h |= (uint8(v.Header.R1) & 0x02)
//h |= (uint8(v.Header.R2) & 0x01)

Expand All @@ -367,14 +382,37 @@ func (v *VRT) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
data[1] = byte(h1)

// The remaining fields can just be copied in big endian order.
binary.BigEndian.PutUint16(data[2:4], uint16(v.Header.PacketSize))
binary.BigEndian.PutUint32(data[4:8], uint32(v.StreamID))
// TODO
//binary.BigEndian.PutUint32(data[4:8], uint32(v.ClassID.OUI))
//binary.BigEndian.PutUint32(data[4:8], uint32(v.ClassID.PacketClassCode))
//binary.BigEndian.PutUint32(data[4:8], uint32(v.ClassID.InformationClassCode))
//binary.BigEndian.PutUint32(data[4:8], uint32(v.TimestampInt))
//binary.BigEndian.PutUint32(data[4:8], uint32(v.TimestampFrac))
binary.BigEndian.PutUint16(data[offset+2:offset+4], uint16(v.Header.PacketSize))

// Update offset for further packet parsing
offset += 4

// Add StreamID when Header.Type == IFDataWithStream || ExtDataWithStream
if (v.Header.Type == IFDataWithStream) || (v.Header.Type == ExtDataWithStream) {
binary.BigEndian.PutUint32(data[offset:offset+4], uint32(v.StreamID))
offset += 4
}

// Set ClassID when Header C is set
if v.Header.C {
binary.BigEndian.PutUint32(data[offset:offset+4], uint32(v.ClassID.OUI))
offset += 4
binary.BigEndian.PutUint16(data[offset:offset+2], uint16(v.ClassID.PacketClassCode))
binary.BigEndian.PutUint16(data[offset+2:offset+4], uint16(v.ClassID.InformationClassCode))
offset += 4
}

// Set Timestamp Integer Seconds
if v.Header.TSI != TSINone {
binary.BigEndian.PutUint32(data[offset:offset+4], uint32(v.TimestampInt))
offset += 4
}

// Set Timestamp Fractional Seconds
if v.Header.TSF != TSFNone {
binary.BigEndian.PutUint64(data[offset:offset+8], uint64(v.TimestampFrac))
offset += 8
}

// Append the VRT Payload based on Payload size
ex, err := b.AppendBytes(len(v.Payload))
Expand All @@ -384,15 +422,15 @@ func (v *VRT) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
copy(ex, v.Payload)

// Add byte padding if Payload does not fall on a byte boundary
res := math.Mod(float64(len(v.Payload)), 4)
if res != 0 {
extraBytePadding := make([]byte, int(res))
ex, err := b.AppendBytes(int(res))
if err != nil {
return err
}
copy(ex, extraBytePadding)
}
// res := math.Mod(float64(len(v.Payload)), 4)
// if res != 0 {
// extraBytePadding := make([]byte, int(res))
// ex, err := b.AppendBytes(int(res))
// if err != nil {
// return err
// }
// copy(ex, extraBytePadding)
// }

return nil
}
Expand Down
63 changes: 56 additions & 7 deletions vrt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,42 @@ var testPacketVRT = []byte{
0x64, 0x6c, 0x65, 0x73, 0x3d, 0x00, 0x00, 0x00,
}

var testPacketVRTPayload = []byte{
0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x33, 0x2e, 0x30, 0x2e, 0x30,
0x2e, 0x31, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x3d, 0x46, 0x4c, 0x45, 0x58, 0x2d, 0x36, 0x37,
0x30, 0x30, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x3d, 0x31, 0x31, 0x31, 0x31, 0x2d, 0x32,
0x32, 0x32, 0x32, 0x2d, 0x33, 0x33, 0x33, 0x33, 0x2d, 0x34, 0x34, 0x34, 0x34, 0x20, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x33, 0x2e, 0x32, 0x2e, 0x33, 0x39, 0x2e, 0x33, 0x33, 0x37,
0x34, 0x20, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x54, 0x45, 0x53, 0x54, 0x31,
0x2f, 0x48, 0x46, 0x2f, 0x41, 0x4d, 0x50, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x67, 0x6e,
0x3d, 0x4e, 0x53, 0x31, 0x48, 0x20, 0x69, 0x70, 0x3d, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38,
0x2e, 0x30, 0x2e, 0x31, 0x31, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x3d, 0x34, 0x39, 0x39, 0x32, 0x20,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
0x20, 0x69, 0x6e, 0x75, 0x73, 0x65, 0x5f, 0x69, 0x70, 0x3d, 0x20, 0x69, 0x6e, 0x75, 0x73, 0x65,
0x5f, 0x68, 0x6f, 0x73, 0x74, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e,
0x73, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x76, 0x33, 0x20, 0x72,
0x61, 0x64, 0x69, 0x6f, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x3d,
0x30, 0x30, 0x2d, 0x31, 0x31, 0x2d, 0x32, 0x32, 0x2d, 0x33, 0x33, 0x2d, 0x34, 0x34, 0x2d, 0x35,
0x35, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x3d, 0x30, 0x20,
0x66, 0x70, 0x63, 0x5f, 0x6d, 0x61, 0x63, 0x3d, 0x20, 0x77, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e,
0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x3d, 0x31, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65,
0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x3d, 0x32, 0x20, 0x61, 0x76, 0x61, 0x69,
0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x3d, 0x32, 0x20,
0x6d, 0x61, 0x78, 0x5f, 0x70, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x73, 0x3d,
0x38, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, 0x61,
0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x73, 0x3d, 0x38, 0x20, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x6c,
0x69, 0x63, 0x65, 0x73, 0x3d, 0x38, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x3d, 0x38, 0x20, 0x67, 0x75, 0x69, 0x5f, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x73, 0x3d, 0x20, 0x67, 0x75, 0x69, 0x5f, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x3d, 0x20, 0x67, 0x75, 0x69, 0x5f,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x3d,
0x20, 0x67, 0x75, 0x69, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x3d, 0x20, 0x67, 0x75, 0x69, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x3d, 0x00, 0x00, 0x00,
}

func checkLayers(p gopacket.Packet, want []gopacket.LayerType, t *testing.T) {
layers := p.Layers()
t.Log("Checking packet layers, want", want)
Expand Down Expand Up @@ -80,26 +116,26 @@ func checkLayers(p gopacket.Packet, want []gopacket.LayerType, t *testing.T) {
func TestVRTSerialization(t *testing.T) {
test_vrt := &vrt.VRT{
Header: vrt.Header{
Type: vrt.ExtData,
Type: vrt.ExtDataWithStream,
C: true,
T: false,
TSI: vrt.TSIUTC,
TSF: vrt.TSFRealTime,
PacketCount: 14,
PacketSize: 6,
TSF: vrt.TSFSampleCount,
PacketCount: 15,
PacketSize: 138,
},
StreamID: 2048,
ClassID: vrt.ClassID{
OUI: 7213,
PacketClassCode: 21324,
InformationClassCode: 65535,
},
TimestampInt: 1687383639,
TimestampInt: 1648594940,
TimestampFrac: 0,
Payload: []byte{0x64, 0x69, 0x73, 0x63},
Payload: testPacketVRTPayload,
}

want := vrt.ExtData
want := vrt.ExtDataWithStream
if want != test_vrt.Header.Type {
t.Fatalf(`vrt.Header.Type = %q, want match for %#q, nil`, test_vrt.Header.Type, want)
}
Expand All @@ -113,6 +149,19 @@ func TestVRTSerialization(t *testing.T) {
if err != nil {
t.Fatalf(`vrt.SerializeTo failed with %s`, err)
}

test_vrt2 := vrt.VRT{}
err = test_vrt2.DecodeFromBytes(buf.Bytes(), gopacket.NilDecodeFeedback)
if err != nil {
t.Fatalf(`Failed to decode Serialized VRT packet back into VRT structure`)
}

assert.Equal(t, test_vrt.Header, test_vrt2.Header, "VRT Packet Headers must match")
assert.Equal(t, test_vrt.StreamID, test_vrt2.StreamID, "VRT Packet StreamID values must match")
assert.Equal(t, test_vrt.ClassID, test_vrt2.ClassID, "VRT Packet ClassID values must match")
assert.Equal(t, test_vrt.TimestampInt, test_vrt2.TimestampInt, "VRT Packet TimestampInt values must match")
assert.Equal(t, test_vrt.TimestampFrac, test_vrt2.TimestampFrac, "VRT Packet TimestampFrac values must match")
assert.Equal(t, test_vrt.Payload, test_vrt2.Payload, "VRT Packet Payload values must match")
}

// TODO: implement VRT Trailer and check for it's presence
Expand Down

0 comments on commit 51da174

Please sign in to comment.