Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions pdu/UDH.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
"github.com/linxGnu/gosmpp/data"
)

// For now, this package only support message uses of UDH for message concatenation
// This package supports message uses of UDH for message concatenation
// Both 8-bit and 16-bit reference numbers are supported for concatenated messages
// No plan for supporting other Enhanced Messaging Service
// Credit to https://github.com/warthog618/sms

Expand Down Expand Up @@ -149,17 +150,29 @@ func (u UDH) FindInfoElement(id byte) (ie *InfoElement, found bool) {
}

// GetConcatInfo return the FIRST concatenated message IE,
func (u UDH) GetConcatInfo() (totalParts, partNum, mref byte, found bool) {
// For 8-bit reference, mref will be a byte value (0-255)
// For 16-bit reference, mref will be a uint16 value (0-65535) converted to uint
func (u UDH) GetConcatInfo() (totalParts, partNum byte, mref uint16, found bool) {
if len(u) == 0 {
found = false
return
}

// Check for 8-bit reference
if ie, ok := u.FindInfoElement(data.UDH_CONCAT_MSG_8_BIT_REF); ok && len(ie.Data) == 3 {
mref = ie.Data[0]
mref = uint16(ie.Data[0])
totalParts = ie.Data[1]
partNum = ie.Data[2]
found = ok
return
}

// Check for 16-bit reference
if ie, ok := u.FindInfoElement(data.UDH_CONCAT_MSG_16_BIT_REF); ok && len(ie.Data) == 4 {
mref = uint16(ie.Data[0])<<8 | uint16(ie.Data[1])
totalParts = ie.Data[2]
partNum = ie.Data[3]
found = ok
}

return
Expand All @@ -173,7 +186,7 @@ type InfoElement struct {
Data []byte
}

// NewIEConcatMessage turn a new IE element for concat message info
// NewIEConcatMessage creates a new IE element for 8-bit concat message info
// IE.Data is populated at time of object creation
func NewIEConcatMessage(totalParts, partNum, mref byte) InfoElement {
return InfoElement{
Expand All @@ -182,6 +195,16 @@ func NewIEConcatMessage(totalParts, partNum, mref byte) InfoElement {
}
}

// NewIEConcatMessage16Bit creates a new IE element for 16-bit concat message info
// IE.Data is populated at time of object creation
// mref is a uint16 value (0-65535)
func NewIEConcatMessage16Bit(totalParts, partNum byte, mref uint16) InfoElement {
return InfoElement{
ID: data.UDH_CONCAT_MSG_16_BIT_REF,
Data: []byte{byte(mref >> 8), byte(mref), byte(totalParts), byte(partNum)},
}
}

// UnmarshalBinary unmarshal IE from binary in src, only read a single IE,
// expect src at least of length 2 with correct IE format:
//
Expand Down
40 changes: 36 additions & 4 deletions pdu/UDH_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,23 @@ func TestUserDataHeader(t *testing.T) {
require.True(t, found)
require.Equal(t, totalParts, byte(2))
require.Equal(t, sequence, byte(1))
require.Equal(t, reference, uint8(12))
require.Equal(t, reference, uint(12))
})

t.Run("unmarshalBinaryUDHConcatMessage", func(t *testing.T) {
t.Run("marshalBinaryUDHConcatMessage (16 bit)", func(t *testing.T) {
u := UDH{NewIEConcatMessage16Bit(2, 1, 1234)}
b, err := u.MarshalBinary()
require.NoError(t, err)
require.Equal(t, "06080404d20201", toHex(b))

totalParts, sequence, reference, found := u.GetConcatInfo()
require.True(t, found)
require.Equal(t, totalParts, byte(2))
require.Equal(t, sequence, byte(1))
require.Equal(t, reference, uint(1234))
})

t.Run("unmarshalBinaryUDHConcatMessage (8 bit)", func(t *testing.T) {
u, rd := new(UDH), []byte{0x05, 0x00, 0x03, 0x0c, 0x02, 0x01}
read, err := u.UnmarshalBinary(rd)
require.False(t, read <= 0)
Expand All @@ -39,10 +52,29 @@ func TestUserDataHeader(t *testing.T) {
require.Equal(t, "0500030c0201", toHex(b))
})

t.Run("unmarshalBinaryUDHConcatMessage (16 bit)", func(t *testing.T) {
u, rd := new(UDH), []byte{0x06, 0x08, 0x04, 0x04, 0xd2, 0x02, 0x01}
read, err := u.UnmarshalBinary(rd)
require.False(t, read <= 0)

require.NoError(t, err)

totalParts, sequence, reference, found := u.GetConcatInfo()
require.True(t, found)
require.Equal(t, totalParts, byte(2))
require.Equal(t, sequence, byte(1))
require.Equal(t, reference, uint(1234))

b, err := u.MarshalBinary()
require.NoError(t, err)
require.Equal(t, "06080404d20201", toHex(b))
})

t.Run("unmarshalBinaryUDHConcatMessage failed", func(t *testing.T) {
failedList := [][]byte{
{0x04, 0x00, 0x02, 0x02, 0x01},
{0x04, 0x08, 0x02, 0x02, 0x01},
{0x04, 0x00, 0x02, 0x02, 0x01}, // Invalid 8-bit UDH (wrong length)
{0x04, 0x08, 0x02, 0x02, 0x01}, // Invalid 16-bit UDH (wrong length)
{0x05, 0x08, 0x03, 0x04, 0xd2, 0x01}, // Invalid 16-bit UDH (missing part number)
}
u := new(UDH)
for _, data := range failedList {
Expand Down