Skip to content

MessageClass mask placement collides with alphabet #159

Open
@ane

Description

@ane

Suppose I want to do the following:

I want to send an uncompressed Message Class 1 with Latin1 alphabet. This would mean, according to the SMPP specification, that I should have a data coding byte that looks like the following.

image

00010101
   ^^^^^ bits 0 and 1 are 01 = message class 1
   | |
   | ` bits 3 and 2 are 01 = 8bit 
   |
   ` the message has a message class (bit 4 is 1)

To do this, I do the following:

new GeneralDataCoding(Alphabet.ALPHA_LATIN1, MessageClass.CLASS1, false)

The byte value of this is translated to 0x13, which is 00010011. What is going on here? It looks like the message class and encoding are encoded at the same position. I should be getting 0x15, which is 00010101.

Let's try with an uncompressed UCS-2 class 0 message. According to the spec, I should be sending

00011000
   ^^^^^ bits 0 and 1 are 00 = message class 0
   | |
   | ` bits 3 and 2 are 10 = UCS2
   |
   ` the message has a message class (bit 4 is 1)

Which is hex 0x18. Doing this in Java

new GeneralDataCoding(Alphabet.ALPHA_UCS2, MessageClass.CLASS0, false);

This looks ok! Ok, to condense this a little bit, a test like this

    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_DEFAULT, null, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_LATIN1, null, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_UCS2, null, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_DEFAULT, MessageClass.CLASS0, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_DEFAULT, MessageClass.CLASS1, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_DEFAULT, MessageClass.CLASS2, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_LATIN1, MessageClass.CLASS0, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_LATIN1, MessageClass.CLASS1, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_LATIN1, MessageClass.CLASS2, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_UCS2, MessageClass.CLASS0, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_UCS2, MessageClass.CLASS1, false).toByte());
    System.out.printf("0x%02X\n", new GeneralDataCoding(Alphabet.ALPHA_UCS2, MessageClass.CLASS2, false).toByte());

prints

0x00    // ok (no class, default alphabet), 0b0000000
0x03    // ok (no class, latin1), 0b0000011
0x08    // ok (no class, ucs2), 0b0001000
0x10    // ok (class, class0, default), 0b0001000
0x11    // ok (class, class1, default), 0b0001001
0x12    // ok (class, class2, default), 0b0001011
0x13   // not ok, class 0 latin1 should be 0b00010100 (0x14) but this is 0b00010011
0x13   // not ok, class 1 latin1 should be 0b00010101 (0x15) but this is 0b00010011
0x13  // not ok, class 2 latin1 should be 0b00010110 (0x16) but this is 0b00010011
0x18  // ok, class 0 ucs-2 should be 0b00011000
0x19  // ok, class 0 ucs-2 should be 0b00011001
0x1A // ok, class 0 ucs-2 should be 0b00011010

So the default alphabet and ucs-2 work just fine, but something is off with latin1.

I think the reason is in the toByte method of GeneralDataCoding:

    public byte toByte() {
        byte value = compressed ? DataCodingFactory00xx.MASK_COMPRESSED : 0;
        value |= alphabet.value();
        if (messageClass != null) {
            value |= DataCodings.MASK_CONTAIN_MESSAGE_CLASS;
            value |= messageClass.value();
        }
        return value;
    }

For alphabets default and ucs-2, the masks are 0b00000000 and 0b00001000. If the message class is defined, this works correctly. But the mask for latin1 is 0x03, 0b00000011. This is the same as the message class mask! So essentially, due to luck, alphabets default and ucs-2 work. What should be done instead is something like

  • If the mask contains no message class, proceed as usual.
  • If the mask contains a message class, the alphabet should be set on bits 3-2 and the message class on bits 0-1.

The reason why I'm opening an issue here is to ask for confirmation. Am I thinking this correctly? According to the specification, IF a message class is defined, the alphabet should move to bits 3-2 and the message class should be on bits 0-1.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions