Skip to content

Commit

Permalink
Supports marshaling of nested IEs
Browse files Browse the repository at this point in the history
  • Loading branch information
linouxis9 committed Apr 4, 2024
1 parent d91a6c9 commit 0c24b46
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 13 deletions.
27 changes: 27 additions & 0 deletions codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,33 @@ var testcases = []struct {
serialized: []byte{0x48, 0x04, 0xde, 0xad, 0xbe, 0xef},
parseFunc: func(b []byte) (serializable, error) { return tcap.ParseIE(b) },
},
{
description: "IE/UserInformation",
structured: func() *tcap.IE {
dialoguePDU := tcap.NewIE(0xa0, []byte{0xde, 0xad, 0xbe, 0xef})

singleAsn1Type := tcap.NewIE(0xa0, []byte{})
singleAsn1Type.IE = []*tcap.IE{dialoguePDU}

directReference := tcap.NewIE(0x06, []byte{04, 00, 00, 01, 01, 01, 01})

userInfoItem := tcap.NewIE(0x28, []byte{})
userInfoItem.IE = []*tcap.IE{directReference, singleAsn1Type}

userInfo := tcap.NewIE(0xBE, []byte{})
userInfo.IE = []*tcap.IE{userInfoItem}

userInfo.SetLength()

return userInfo
}(),
serialized: []byte{
0xbe, 0x13, 0x28, 0x11, 0x06, 0x07, 0x04,
0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xa0,
0x06, 0xa0, 0x04, 0xde, 0xad, 0xbe, 0xef,
},
parseFunc: func(b []byte) (serializable, error) { return tcap.ParseIERecursive(b) },
},
}

func TestCodec(t *testing.T) {
Expand Down
20 changes: 18 additions & 2 deletions 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])

Check failure on line 375 in component.go

View workflow job for this annotation

GitHub Actions / lint

ST1005: error strings should not be capitalized (stylecheck)
}

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 @@ -434,12 +441,16 @@ func (c *Component) UnmarshalBinary(b []byte) error {
offset += c.OperationCode.MarshalLen()

if offset >= len(b) {
c.ResultRetres.Value = []byte{}
return nil
}
c.Parameter, err = ParseIERecursive(b[offset:])
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 +471,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])

Check failure on line 477 in component.go

View workflow job for this annotation

GitHub Actions / lint

ST1005: error strings should not be capitalized (stylecheck)
}

return nil
}

Expand All @@ -478,14 +495,13 @@ func (c *Component) setParameterFromBytes(b []byte) error {
Tag: NewUniversalConstructorTag(0x10),
Value: b,
}

return nil
}

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 @@ -386,7 +386,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 @@ -396,14 +396,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])

Check failure on line 414 in dialogue-pdu.go

View workflow job for this annotation

GitHub Actions / lint

ST1005: error strings should not be capitalized (stylecheck)
}

return nil
}

func (d *DialoguePDU) parseAARQFromBytes(b []byte) error {
Expand Down
2 changes: 1 addition & 1 deletion dialogue.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func (d *Dialogue) MarshalLen() int {
l += field.MarshalLen()
}
if field := d.DialoguePDU; field != nil {
l += field.MarshalLen() + 2 // 2 = singleAsn1Type IE Header
l += field.MarshalLen() + 2 // 2 = SingleAsn1Type IE Header
}

return l + len(d.Payload)
Expand Down
36 changes: 31 additions & 5 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])

Check failure on line 184 in ie.go

View workflow job for this annotation

GitHub Actions / lint

ST1005: error strings should not be capitalized (stylecheck)
}
return nil
}

Expand Down Expand Up @@ -228,7 +244,7 @@ func (i *IE) ParseRecursive(b []byte) error {
i.Tag = Tag(b[0])
i.Length = b[1]
if int(i.Length)+2 > len(b) {
return nil
return io.ErrUnexpectedEOF
}
i.Value = b[2 : 2+int(i.Length)]

Expand All @@ -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)

Check failure on line 166 in tcap.go

View workflow job for this annotation

GitHub Actions / lint

ST1005: error strings should not be capitalized (stylecheck)
}

return nil
Expand Down

0 comments on commit 0c24b46

Please sign in to comment.