98 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
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
 | 
						|
}
 |