package pdu import ( "encoding/binary" "fmt" ) type ( PDU interface { EncodeInto(*[]uint8) Encode() []uint8 Decode([]uint8) // Size in bytes Size() uint32 } PDU_HEADER struct { command_length uint32 command_id uint32 command_status uint32 sequence_number uint32 } GENERIC_NACK struct { header PDU_HEADER } ) // Hmm the header can be partially encoded // As in command_status can just be null // So not 0s, null, non existent, not encoded // So we'll have to maybe set them to nil or something... // Wireshark dump of a submit_sm // See header: 00 00 00 3e (size, 62 bytes), 00 00 00 04 (command_id), status and sequence number are 0 // So they are not encoded // Here the header is 8 bytes, not 16 // 0000 02 00 00 00 45 00 00 66 6f ff 40 00 80 06 00 00 ....E..fo.@..... // 0010 7f 00 00 01 7f 00 00 01 31 4f 0a d7 e8 b0 b1 b5 ........1O...... // 0020 3e 91 d9 dc 50 18 20 fa 2a 1f 00 00 00 00 00 3e >...P. .*......> // 0030 00 00 00 04 00 00 00 00 00 00 00 02 00 00 00 73 ...............s // 0040 6d 70 70 5f 74 65 73 74 5f 31 00 00 00 31 32 33 mpp_test_1...123 // 0050 31 32 33 31 32 33 31 32 33 00 00 00 00 00 00 00 123123123....... // 0060 00 c0 00 06 48 65 6c 6c 6f 21 ....Hello! // I AM NOT RIGHT // Beyond the size and command_id, command_status and sequence_number here are: // 00 00 00 00 (0) 00 00 00 02 (2) // // Another example - bind_transciever: // 0000 02 00 00 00 45 00 00 47 6f fb 40 00 80 06 00 00 ....E..Go.@..... // 0010 7f 00 00 01 7f 00 00 01 31 4f 0a d7 e8 b0 b1 96 ........1O...... // 0020 3e 91 d9 cb 50 18 20 fa df ab 00 00 00 00 00 1f >...P. ......... // 0030 00 00 00 09 00 00 00 00 00 00 00 01 74 65 73 74 ............test // 0040 00 74 65 73 74 00 00 50 00 00 00 .test..P... // 00 00 00 1f - 00 00 00 09 - 00 00 00 00 - 00 00 00 01 (header) // 74 65 73 74 00 - 74 65 73 74 00 - 00 50 00 00 00 // ^system_id ^password ^interface_version // What are the other 0s? // Don't know func (p *PDU_HEADER) Encode() (*[]uint8, error) { buf := ByteBufferPool.Get(uint(p.Size())) err := p.EncodeInto(buf) return buf, err } func (p *PDU_HEADER) EncodeInto(buf *[]uint8) error { if buf == nil { return fmt.Errorf("cannot encode PDU_HEADER, buffer is nil") } if len(*buf) < 16 { return fmt.Errorf("cannot encode PDU_HEADER, buffer too small (%d, required 16)", len(*buf)) } bufVal := *buf binary.BigEndian.PutUint32(bufVal[0:4], p.command_length) binary.BigEndian.PutUint32(bufVal[4:8], p.command_id) binary.BigEndian.PutUint32(bufVal[8:12], p.command_status) binary.BigEndian.PutUint32(bufVal[12:16], p.sequence_number) return nil } func (p *PDU_HEADER) Decode(data []uint8) error { if len(data) >= 4 { p.command_length = binary.BigEndian.Uint32(data[0:4]) } if len(data) >= 8 { p.command_id = binary.BigEndian.Uint32(data[4:8]) } if len(data) >= 12 { p.command_status = binary.BigEndian.Uint32(data[8:12]) } if len(data) >= 16 { p.sequence_number = binary.BigEndian.Uint32(data[12:16]) } return nil } func (p *PDU_HEADER) Size() uint32 { return 16 }