Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Commit

Permalink
chore: Restructures ie deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
gruyaume committed Jan 7, 2024
1 parent 807650a commit 8da338f
Show file tree
Hide file tree
Showing 13 changed files with 393 additions and 353 deletions.
34 changes: 12 additions & 22 deletions ie/cause.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ package ie

import (
"bytes"
"encoding/binary"
"fmt"
)

type Cause struct {
IEType uint16
Length uint16
Header IEHeader
Value CauseValue
}

Expand Down Expand Up @@ -40,21 +38,22 @@ func NewCause(value CauseValue) (Cause, error) {
return Cause{}, fmt.Errorf("invalid value for Cause: %d", value)
}

return Cause{
IEType: uint16(CauseIEType),
header := IEHeader{
Type: CauseIEType,
Length: 1,
}

return Cause{
Header: header,
Value: value,
}, nil
}

func (cause Cause) Serialize() []byte {
buf := new(bytes.Buffer)

// Octets 1 to 2: Type
binary.Write(buf, binary.BigEndian, uint16(cause.IEType))

// Octets 3 to 4: Length
binary.Write(buf, binary.BigEndian, uint16(cause.Length))
// Octets 1 to 4: Header
buf.Write(cause.Header.Serialize())

// Octet 5: Value (1 byte)
buf.WriteByte(uint8(cause.Value))
Expand All @@ -63,27 +62,18 @@ func (cause Cause) Serialize() []byte {
}

func (cause Cause) IsZeroValue() bool {
return cause.Length == 0
return cause.Value == 0
}

func DeserializeCause(ieType uint16, ieLength uint16, ieValue []byte) (Cause, error) {
func DeserializeCause(ieHeader IEHeader, ieValue []byte) (Cause, error) {
var cause Cause

if len(ieValue) != 1 {
return cause, fmt.Errorf("invalid length for Cause: got %d bytes, want 1", len(ieValue))
}

if ieType != uint16(CauseIEType) {
return cause, fmt.Errorf("invalid IE type: expected %d, got %d", CauseIEType, ieType)
}

if ieLength != 1 {
return cause, fmt.Errorf("invalid length field for Cause: expected 1, got %d", ieLength)
}

return Cause{
IEType: ieType,
Length: ieLength,
Header: ieHeader,
Value: CauseValue(ieValue[0]),
}, nil
}
63 changes: 41 additions & 22 deletions ie/ie.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ func (ieHeader *IEHeader) Serialize() []byte {
return buf.Bytes()
}

func DeserializeIEHeader(payload []byte) (IEHeader, error) {
var ieHeader IEHeader

if len(payload) < IEHeaderLength {
return ieHeader, fmt.Errorf("not enough bytes for IE header")
}

ieHeader.Type = IEType(binary.BigEndian.Uint16(payload[:2]))
ieHeader.Length = binary.BigEndian.Uint16(payload[2:4])

return ieHeader, nil
}

type InformationElement interface {
Serialize() []byte
IsZeroValue() bool
Expand All @@ -65,54 +78,60 @@ func ParseInformationElements(b []byte) ([]InformationElement, error) {
ieType := IEType(binary.BigEndian.Uint16(b[index : index+2]))
ieLength := binary.BigEndian.Uint16(b[index+2 : index+4])
index += IEHeaderLength
if len(b[index:]) < int(ieLength) {
return nil, fmt.Errorf("not enough bytes for IE data, expected %d, got %d", ieLength, len(b[index:]))

ieHeader := IEHeader{
Type: ieType,
Length: ieLength,
}

if len(b[index:]) < int(ieHeader.Length) {
return nil, fmt.Errorf("not enough bytes for IE data, expected %d, got %d", ieHeader.Length, len(b[index:]))
}

ieValue := b[index : index+int(ieLength)]
ieValue := b[index : index+int(ieHeader.Length)]
var ie InformationElement
switch ieType {
switch ieHeader.Type {
case CauseIEType:
ie, err = DeserializeCause(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeCause(ieHeader, ieValue)
case NodeIDIEType:
ie, err = DeserializeNodeID(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeNodeID(ieHeader, ieValue)
case RecoveryTimeStampIEType:
ie, err = DeserializeRecoveryTimeStamp(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeRecoveryTimeStamp(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case NodeReportTypeIEType:
ie, err = DeserializeNodeReportType(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeNodeReportType(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case SourceIPAddressIEType:
ie, err = DeserializeSourceIPAddress(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeSourceIPAddress(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case UPFunctionFeaturesIEType:
ie, err = DeserializeUPFunctionFeatures(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeUPFunctionFeatures(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case FSEIDIEType:
ie, err = DeserializeFSEID(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeFSEID(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case PDRIDIEType:
ie, err = DeserializePDRID(uint16(ieType), ieLength, ieValue)
ie, err = DeserializePDRID(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case PrecedenceIEType:
ie, err = DeserializePrecedence(uint16(ieType), ieLength, ieValue)
ie, err = DeserializePrecedence(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case SourceInterfaceIEType:
ie, err = DeserializeSourceInterface(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeSourceInterface(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case PDIIEType:
ie, err = DeserializePDI(uint16(ieType), ieLength, ieValue)
ie, err = DeserializePDI(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case CreatePDRIEType:
ie, err = DeserializeCreatePDR(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeCreatePDR(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case FARIDIEType:
ie, err = DeserializeFARID(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeFARID(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case ApplyActionIEType:
ie, err = DeserializeApplyAction(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeApplyAction(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case CreateFARIEType:
ie, err = DeserializeCreateFAR(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeCreateFAR(uint16(ieHeader.Type), ieHeader.Length, ieValue)
case ReportTypeIEType:
ie, err = DeserializeReportType(uint16(ieType), ieLength, ieValue)
ie, err = DeserializeReportType(uint16(ieHeader.Type), ieHeader.Length, ieValue)
default:
err = fmt.Errorf("unknown IE type %d", ieType)
err = fmt.Errorf("unknown IE type %d", ieHeader.Type)
}

if ie != nil {
ies = append(ies, ie)
}

index += int(ieLength)
index += int(ieHeader.Length)
}

return ies, err
Expand Down
47 changes: 21 additions & 26 deletions ie/nodeId.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ie

import (
"bytes"
"encoding/binary"
"fmt"
"net"
)
Expand All @@ -16,10 +15,9 @@ const (
type NodeIDType int

type NodeID struct {
IEtype uint16
Length uint16
NodeIDType NodeIDType
NodeIDValue []byte
Header IEHeader
Type NodeIDType
Value []byte
}

func NewNodeID(nodeID string) (NodeID, error) {
Expand All @@ -46,54 +44,52 @@ func NewNodeID(nodeID string) (NodeID, error) {
length = uint16(len(nodeIDValueBytes)) + 1
nodeIDType = FQDN
}

header := IEHeader{
Type: NodeIDIEType,
Length: length,
}
return NodeID{
IEtype: uint16(NodeIDIEType),
Length: length,
NodeIDType: nodeIDType,
NodeIDValue: nodeIDValueBytes,
Header: header,
Type: nodeIDType,
Value: nodeIDValueBytes,
}, nil
}

func (n NodeID) Serialize() []byte {
buf := new(bytes.Buffer)

// Octets 1 to 2: Type
binary.Write(buf, binary.BigEndian, uint16(n.IEtype))

// Octets 3 to 4: Length
binary.Write(buf, binary.BigEndian, uint16(n.Length))
// Octets 1 to 4: Header
buf.Write(n.Header.Serialize())

// Octet 5: Spare (4 bits) + Node ID Type (4 bits)
spareAndType := byte(n.NodeIDType & 0x0F) // Ensure NodeIDType is only 4 bits
spareAndType := byte(n.Type & 0x0F) // Ensure NodeIDType is only 4 bits
buf.WriteByte(spareAndType)

// Octets 6 to n+5: Node ID Value
buf.Write(n.NodeIDValue)
buf.Write(n.Value)

return buf.Bytes()
}

func (n NodeID) IsZeroValue() bool {
return n.Length == 0
return n.Header.Length == 0
}

func DeserializeNodeID(ieType uint16, ieLength uint16, ieValue []byte) (NodeID, error) {
func DeserializeNodeID(ieHeader IEHeader, ieValue []byte) (NodeID, error) {
var nodeID NodeID

if len(ieValue) < 1 {
return nodeID, fmt.Errorf("invalid length for NodeID: got %d bytes, expected at least 1", len(ieValue))
}

if ieType != uint16(NodeIDIEType) {
return nodeID, fmt.Errorf("invalid IE type: expected %d, got %d", NodeIDIEType, ieType)
if uint16(ieHeader.Type) != uint16(NodeIDIEType) {
return nodeID, fmt.Errorf("invalid IE type: expected %d, got %d", NodeIDIEType, ieHeader.Type)
}

nodeIDType := NodeIDType(ieValue[0] & 0x0F)
if nodeIDType != IPv4 && nodeIDType != IPv6 && nodeIDType != FQDN {
return nodeID, fmt.Errorf("invalid NodeIDType: %d", nodeIDType)
}

switch nodeIDType {
case IPv4:
if len(ieValue[1:]) != net.IPv4len {
Expand All @@ -106,10 +102,9 @@ func DeserializeNodeID(ieType uint16, ieLength uint16, ieValue []byte) (NodeID,
}

nodeID = NodeID{
IEtype: ieType,
Length: ieLength,
NodeIDType: nodeIDType,
NodeIDValue: ieValue[1:],
Header: ieHeader,
Type: nodeIDType,
Value: ieValue[1:],
}

return nodeID, nil
Expand Down
Loading

0 comments on commit 8da338f

Please sign in to comment.