Skip to content

Commit

Permalink
Support for marshaling nested IEs
Browse files Browse the repository at this point in the history
  • Loading branch information
linouxis9 committed Mar 26, 2024
1 parent 53661cd commit 0d6f894
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 18 deletions.
8 changes: 0 additions & 8 deletions codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ var testcases = []struct {
}
// clear unnecessary payload
v.Transaction.Payload = nil
v.Dialogue.SingleAsn1Type.Value = nil
v.Dialogue.Payload = nil

return v, nil
Expand Down Expand Up @@ -88,7 +87,6 @@ var testcases = []struct {
}
// clear unnecessary payload
v.Transaction.Payload = nil
v.Dialogue.SingleAsn1Type.Value = nil
v.Dialogue.Payload = nil
v.Components.Component[0].ResultRetres.Value = nil

Expand Down Expand Up @@ -121,7 +119,6 @@ var testcases = []struct {
}
// clear unnecessary payload
v.Transaction.Payload = nil
v.Dialogue.SingleAsn1Type.Value = nil
v.Dialogue.Payload = nil
v.Components.Component[0].Parameter.IE = nil

Expand Down Expand Up @@ -220,7 +217,6 @@ var testcases = []struct {
}
// clear unnecessary payload
v.Transaction.Payload = nil
v.Dialogue.SingleAsn1Type.Value = nil
v.Dialogue.Payload = nil
v.Components.Component[0].ResultRetres.Value = nil
v.Components.Component[0].Parameter.IE = nil
Expand Down Expand Up @@ -282,8 +278,6 @@ var testcases = []struct {
if err != nil {
return nil, err
}
// clear unnecessary payload
v.SingleAsn1Type.Value = nil

return v, nil
},
Expand All @@ -309,8 +303,6 @@ var testcases = []struct {
if err != nil {
return nil, err
}
// clear unnecessary payload
v.SingleAsn1Type.Value = nil

return v, nil
},
Expand Down
18 changes: 17 additions & 1 deletion component.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,12 @@ func (c *Components) UnmarshalBinary(b []byte) error {
}
b = b[offset+comp.MarshalLen()-2:]
}

c.SetLength()
if b[1] != c.Length {
return fmt.Errorf("Decoded Length is not equal to Components Length, got %d, expected %d", c.Length, b[1])
}

return nil
}

Expand All @@ -388,6 +394,7 @@ func (c *Component) UnmarshalBinary(b []byte) error {
}
c.Type = Tag(b[0])
c.Length = b[1]
expectedLength := b[1]

var err error
var offset = 2
Expand Down Expand Up @@ -440,6 +447,9 @@ func (c *Component) UnmarshalBinary(b []byte) error {
if err != nil {
return err
}
offset += c.Parameter.MarshalLen()
c.ResultRetres.Value = c.ResultRetres.Value[offset:]

case ReturnError:
c.ErrorCode, err = ParseIE(b[offset:])
if err != nil {
Expand All @@ -460,6 +470,12 @@ func (c *Component) UnmarshalBinary(b []byte) error {
return err
}
}

c.SetLength()
if expectedLength != c.Length {
return fmt.Errorf("Decoded Length is not equal to Component Length, got %d, expected %d", c.Length, b[1])
}

return nil
}

Expand All @@ -485,7 +501,7 @@ func (c *Component) setParameterFromBytes(b []byte) error {
c.Parameter = &IE{
// TODO: tag should not be determined here.
Tag: NewUniversalConstructorTag(0x10),
Value: b,
Value: []byte{}, // If we were able to parse the IEs, do not set value
IE: ies,
}
return nil
Expand Down
21 changes: 16 additions & 5 deletions dialogue-pdu.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ func ParseDialoguePDU(b []byte) (*DialoguePDU, error) {
}

// UnmarshalBinary sets the values retrieved from byte sequence in an DialoguePDU.
func (d *DialoguePDU) UnmarshalBinary(b []byte) error {
func (d *DialoguePDU) UnmarshalBinary(b []byte) (err error) {
if len(b) < 4 {
return io.ErrUnexpectedEOF
}
Expand All @@ -398,14 +398,25 @@ func (d *DialoguePDU) UnmarshalBinary(b []byte) error {

switch d.Type.Code() {
case AARQ:
return d.parseAARQFromBytes(b)
err = d.parseAARQFromBytes(b)
case AARE:
return d.parseAAREFromBytes(b)
err = d.parseAAREFromBytes(b)
case ABRT:
return d.parseABRTFromBytes(b)
err = d.parseABRTFromBytes(b)
default:
return &InvalidCodeError{Code: d.Type.Code()}
err = &InvalidCodeError{Code: d.Type.Code()}
}

if err != nil {
return
}

d.SetLength()
if b[1] != d.Length {
return fmt.Errorf("Decoded Length is not equal to DialoguePDU Length, got %d, expected %d", d.Length, b[1])
}

return nil
}

func (d *DialoguePDU) parseAARQFromBytes(b []byte) error {
Expand Down
34 changes: 30 additions & 4 deletions ie.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,24 @@ func (i *IE) MarshalBinary() ([]byte, error) {

// MarshalTo puts the byte sequence in the byte array given as b.
func (i *IE) MarshalTo(b []byte) error {
var offset = 2

if len(b) < 2 {
return io.ErrUnexpectedEOF
}

b[0] = uint8(i.Tag)
b[1] = i.Length
copy(b[2:i.MarshalLen()], i.Value)

offset += copy(b[offset:], i.Value)

for _, childIE := range i.IE {
if err := childIE.MarshalTo(b[offset : offset+childIE.MarshalLen()]); err != nil {
return err
}
offset += childIE.MarshalLen()
}

return nil
}

Expand Down Expand Up @@ -167,6 +178,11 @@ func (i *IE) UnmarshalBinary(b []byte) error {
return io.ErrUnexpectedEOF
}
i.Value = b[2 : 2+int(i.Length)]

i.SetLength()
if b[1] != i.Length {
return fmt.Errorf("Decoded Length is not equal to IE Length, got %d, expected %d", i.Length, b[1])
}
return nil
}

Expand Down Expand Up @@ -238,19 +254,29 @@ func (i *IE) ParseRecursive(b []byte) error {
return nil
}
i.IE = append(i.IE, x...)
}

i.Value = b[2+int(i.Length):]
}
return nil
}

// MarshalLen returns the serial length of IE.
func (i *IE) MarshalLen() int {
return 2 + len(i.Value)
l := 2
for _, childIE := range i.IE {
l += childIE.MarshalLen()
}

return l + len(i.Value)
}

// SetLength sets the length in Length field.
func (i *IE) SetLength() {
i.Length = uint8(len(i.Value))
for _, childIE := range i.IE {
childIE.SetLength()
}

i.Length = uint8(i.MarshalLen() - 2)
}

// String returns IE in human readable string.
Expand Down
14 changes: 14 additions & 0 deletions tcap.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ func (t *TCAP) UnmarshalBinary(b []byte) error {
var offset = 0

t.Transaction, err = ParseTransaction(b[offset:])
transactionLength := t.Transaction.Length
if err != nil {
return err
}
Expand All @@ -140,16 +141,29 @@ func (t *TCAP) UnmarshalBinary(b []byte) error {
if len(t.Dialogue.Payload) == 0 {
return nil
}
// Dialogue is not a Transaction Payload
// We have to remove Dialogue from the Payload
// Or mashaling an unmarshaled message will write back two times the Dialogue
t.Transaction.Payload = t.Transaction.Payload[t.Dialogue.MarshalLen():]

t.Components, err = ParseComponents(t.Dialogue.Payload)
if err != nil {
return err
}

// Same as above but Components inside Dialogue Payload
t.Dialogue.Payload = t.Dialogue.Payload[t.Components.MarshalLen():]
case 0x6c:
t.Components, err = ParseComponents(t.Transaction.Payload)
if err != nil {
return err
}
t.Transaction.Payload = t.Transaction.Payload[t.Components.MarshalLen():]
}

t.SetLength()
if transactionLength != t.Transaction.Length {
return fmt.Errorf("Decoded Length is not equal to Transaction Length, got %d, expected %d", t.Transaction.Length, transactionLength)
}

return nil
Expand Down

0 comments on commit 0d6f894

Please sign in to comment.