42d1e6e991
Add a main loop, move I/O code into io.go, move configuration into config.go. Use shared.Decode24BitLength instead of manually decoding block lengths. Fix response block decoding and checksum validation. Add constants for commonly used byte values and use these in the signer and the client.
86 lines
2.7 KiB
Go
86 lines
2.7 KiB
Go
package datastructures
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type SignerRequest struct {
|
|
Version uint8
|
|
Action Action
|
|
System uint8
|
|
Root uint8
|
|
Configuration uint8
|
|
Parameter1 uint8
|
|
Parameter2 uint16
|
|
Parameter3 uint8
|
|
Content1 string
|
|
Content2 string
|
|
Content3 string
|
|
}
|
|
|
|
const protocolVersion = 1
|
|
|
|
func SignerRequestFromData(lengthBytes []byte, blockData []byte, checkSum byte) (*SignerRequest, error) {
|
|
headerLength := Decode24BitLength(blockData[0:3])
|
|
headerBytes := blockData[3 : 3+headerLength]
|
|
|
|
contentBytes := blockData[3+headerLength:]
|
|
content1Length := Decode24BitLength(contentBytes[0:3])
|
|
content1 := string(contentBytes[3 : 3+content1Length])
|
|
|
|
content2Offset := 3 + content1Length
|
|
content2Length := Decode24BitLength(contentBytes[content2Offset : content2Offset+3])
|
|
content2 := string(contentBytes[3+content2Offset : 3+content2Offset+content2Length])
|
|
|
|
content3Offset := 3 + content2Offset + content2Length
|
|
content3Length := Decode24BitLength(contentBytes[content3Offset : content3Offset+3])
|
|
content3 := string(contentBytes[3+content3Offset : 3+content3Offset+content3Length])
|
|
|
|
calculated := CalculateXorCheckSum([][]byte{lengthBytes, blockData})
|
|
if checkSum != calculated {
|
|
return nil, errors.New(fmt.Sprintf("invalid checksum expected 0x%x got 0x%x", calculated, checkSum))
|
|
}
|
|
return &SignerRequest{
|
|
Version: headerBytes[0],
|
|
Action: Action(headerBytes[1]),
|
|
System: headerBytes[2],
|
|
Root: headerBytes[3],
|
|
Configuration: headerBytes[4],
|
|
Parameter1: headerBytes[5],
|
|
Parameter2: binary.BigEndian.Uint16([]byte{headerBytes[6], headerBytes[7]}),
|
|
Parameter3: headerBytes[8],
|
|
Content1: content1,
|
|
Content2: content2,
|
|
Content3: content3,
|
|
}, nil
|
|
}
|
|
|
|
func (r SignerRequest) Serialize() []byte {
|
|
parameter2Bytes := make([]byte, 2)
|
|
binary.BigEndian.PutUint16(parameter2Bytes, r.Parameter2)
|
|
headerBytes := bytes.Join([][]byte{
|
|
{r.Version, byte(r.Action), r.System, r.Root, r.Configuration, r.Parameter1},
|
|
parameter2Bytes, {r.Parameter3}}, []byte{})
|
|
content1Bytes := []byte(r.Content1)
|
|
content2Bytes := []byte(r.Content2)
|
|
content3Bytes := []byte(r.Content3)
|
|
blockBytes := bytes.Join([][]byte{
|
|
encode24BitLength(headerBytes), headerBytes,
|
|
encode24BitLength(content1Bytes), content1Bytes,
|
|
encode24BitLength(content2Bytes), content2Bytes,
|
|
encode24BitLength(content3Bytes), content3Bytes,
|
|
}, []byte{})
|
|
return bytes.Join([][]byte{encode24BitLength(blockBytes), blockBytes}, []byte{})
|
|
}
|
|
|
|
func NewNulRequest() *SignerRequest {
|
|
return &SignerRequest{
|
|
Version: protocolVersion,
|
|
Action: ActionNul,
|
|
Content1: time.Now().UTC().Format("010203042006.05"),
|
|
}
|
|
}
|