Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
68
pkg/utils/vod/crc.go
Normal file
68
pkg/utils/vod/crc.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package vod
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/sigurn/crc8"
|
||||
)
|
||||
|
||||
func NewVODHelper(lengthInCRC bool,
|
||||
crcInLength bool,
|
||||
lengthInLength bool) VODHelper {
|
||||
return VODHelper{
|
||||
table: crc8.MakeTable(crc8.Params{
|
||||
Poly: 0x1D,
|
||||
Init: 0,
|
||||
RefIn: false,
|
||||
RefOut: false,
|
||||
XorOut: 0,
|
||||
Check: 0,
|
||||
Name: "CEC-8 VOD",
|
||||
}),
|
||||
lengthInCRC: lengthInCRC,
|
||||
crcInLength: crcInLength,
|
||||
lengthInLength: lengthInLength,
|
||||
}
|
||||
}
|
||||
|
||||
type VODHelper struct {
|
||||
table *crc8.Table
|
||||
lengthInCRC bool
|
||||
crcInLength bool
|
||||
lengthInLength bool
|
||||
}
|
||||
|
||||
// Given a list of bytes, we calculate our custom CRC-8 on it, then prepend the length and postpend the crc in place of last byte
|
||||
// So 0x01 0x02 0x00 -> 0x00 0x05 0x01 0x02 0x00 0xCRC-8(0x01 0x02 0x00)
|
||||
// If you have an existing VOD that you are modifying, this function expects you to have removed the length and the crc
|
||||
func (v *VODHelper) AddLengthAndCRC(data []byte) []byte {
|
||||
// first 2 bytes are length including length bytes
|
||||
length := make([]byte, 2)
|
||||
lengthPlus := 0
|
||||
if v.crcInLength { // No
|
||||
lengthPlus += 1
|
||||
}
|
||||
if v.lengthInLength { // Yes
|
||||
lengthPlus += 2
|
||||
}
|
||||
binary.BigEndian.PutUint16(length, uint16(len(data)+lengthPlus))
|
||||
|
||||
var crc byte
|
||||
if v.lengthInCRC { // no
|
||||
data = append(length, data...)
|
||||
// calculate crc on data only
|
||||
crc = v.GenerateCRC(data)
|
||||
} else { // yes
|
||||
// calculate crc on data only
|
||||
crc = v.GenerateCRC(data)
|
||||
data = append(length, data...)
|
||||
}
|
||||
data = append(data, crc)
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func (v *VODHelper) GenerateCRC(data []byte) byte {
|
||||
crc := crc8.Checksum(data, v.table)
|
||||
return crc
|
||||
}
|
||||
133
pkg/utils/vod/crc_test.go
Normal file
133
pkg/utils/vod/crc_test.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package vod
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCustomCRC(t *testing.T) {
|
||||
inputString := "2301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000FFFFFF0000000201010202000101"
|
||||
|
||||
inputB, err := hex.DecodeString(inputString)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
p := NewVODHelper(false, false, false)
|
||||
output := p.GenerateCRC(inputB)
|
||||
if output != 0x5F {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoesMatchReport(t *testing.T) {
|
||||
reported := "00A92301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000FFFFFF00000002010102020001015F"
|
||||
reportedBytes, err := hex.DecodeString(reported)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
inputBytes := reportedBytes[2 : len(reportedBytes)-1]
|
||||
p := NewVODHelper(false, false, true)
|
||||
outputBytes := p.AddLengthAndCRC(inputBytes)
|
||||
|
||||
if len(reportedBytes) != len(outputBytes) {
|
||||
t.Logf("Lengths did not match %d %d", len(reportedBytes), len(outputBytes))
|
||||
t.Fail()
|
||||
}
|
||||
if !bytes.Equal(outputBytes, reportedBytes) {
|
||||
t.Log("input and output did not match")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestLengthOfFinal(t *testing.T) {
|
||||
inputString := "2EF1110102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798990001020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626399"
|
||||
inputB, err := hex.DecodeString(inputString)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Expect the length to be increased by 2 from pre-pending length
|
||||
p := NewVODHelper(false, false, true)
|
||||
output := p.AddLengthAndCRC(inputB)
|
||||
if len(output) != len(inputB)+3 {
|
||||
t.Logf("Expected a final length of %d but got %d", len(inputB)+3, len(output))
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
length := binary.BigEndian.Uint16(output[:2])
|
||||
// Don't include crc with length
|
||||
if int64(length) != int64(len(output)-1) {
|
||||
t.Logf("The calculated length does not match actual length %d %d", int64(length), int64(len(output)-1))
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestCRCCorrect(t *testing.T) {
|
||||
inputString := "00112233"
|
||||
inputB, err := hex.DecodeString(inputString)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Expect the length to be increased by 2 from pre-pending length
|
||||
p := NewVODHelper(false, true, false)
|
||||
output := p.GenerateCRC(inputB)
|
||||
secondStep := append(inputB, output)
|
||||
|
||||
output2 := p.GenerateCRC(secondStep)
|
||||
if output2 != 0x00 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestCRCCorrect2(t *testing.T) {
|
||||
inputString := "00112233"
|
||||
inputB, err := hex.DecodeString(inputString)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Expect the length to be increased by 2 from pre-pending length
|
||||
p := NewVODHelper(false, false, false)
|
||||
output := p.AddLengthAndCRC(inputB)
|
||||
// Chopping out length
|
||||
output = output[2:]
|
||||
output2 := p.GenerateCRC(output)
|
||||
if output2 != 0x00 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestCRCTotalZero(t *testing.T) {
|
||||
p := NewVODHelper(false, false, true)
|
||||
inputString := "030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798990001020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626399"
|
||||
inputB, err := hex.DecodeString(inputString)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
crc := p.GenerateCRC(inputB)
|
||||
if crc != 0x00 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestCRCAndLengthSame(t *testing.T) {
|
||||
inputString := "01012301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000FFFFFF000101020101020200010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BA"
|
||||
inputBytes, err := hex.DecodeString(inputString)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
//Removing the length and the CRC
|
||||
p := NewVODHelper(false, false, true)
|
||||
choppedInput := inputBytes[2 : len(inputBytes)-1]
|
||||
choppedInput = p.AddLengthAndCRC(choppedInput)
|
||||
if !bytes.Equal(inputBytes, choppedInput) {
|
||||
t.Log("CRC and length not calculated as expected")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user