package testclient import ( "encoding/binary" "errors" "ripple/crypto" "ripple/tests/internal/testclient/udpr" ) var errInvalidUserRequest = errors.New("invalid user request") var errInvalidSignature = errors.New("invalid signature") var errCounterMismatch = errors.New("not a response to the sent counter") const userType = 0x01 type clientTransport struct { c *udpr.UDPRClient secretKey [32]byte } func newClientTransport(c *udpr.UDPRClient, secretKey [32]byte) *clientTransport { return &clientTransport{c: c, secretKey: secretKey} } func (t *clientTransport) receive(counterSent uint32) (byte, []byte, error) { payload, err := t.c.Read() if err != nil { return 0, nil, err } if len(payload) < 5+32 { return 0, nil, errInvalidUserRequest } if !crypto.VerifySignature(payload, t.secretKey) { return 0, nil, errInvalidSignature } counter := binary.BigEndian.Uint32(payload[0:4]) if counter != counterSent { return 0, nil, errCounterMismatch } status := payload[4] data := payload[5 : len(payload)-32] return status, data, nil } func (t *clientTransport) send(req UserRequest) { buf := make([]byte, 5) buf[0] = userType binary.BigEndian.PutUint32(buf[1:5], req.Counter) buf = append(buf, req.Instruction.Command) buf = append(buf, req.Instruction.Arguments...) signed := crypto.SignData(buf, t.secretKey) go func() { if err := t.c.Write(signed); err != nil { panic(err) } }() }