package transport import ( "encoding/binary" "net" "ripple/crypto" "ripple/types" "ripple/udpr" ) type UserTransport struct { d *Data c *udpr.UDPRConn w *userSenderWorker } func NewUserTransport(c *udpr.UDPRConn, d *Data) *UserTransport { t := &UserTransport{d: d, c: c} t.w = newUserSenderWorker(t) return t } func (t *UserTransport) Receive(data []byte, addr *net.UDPAddr) (types.UserRequest, error) { if len(data) < 6+32 { return types.UserRequest{}, errInvalidUserRequest } if !crypto.VerifySignature(data, t.d.Storage.User.SecretKey) { return types.UserRequest{}, errInvalidUserRequest } counter := binary.BigEndian.Uint32(data[1:5]) if counter <= t.d.Storage.User.Counter { return types.UserRequest{}, errInvalidUserRequest } if err := t.d.setUserCounter(counter); err != nil { return types.UserRequest{}, err } cmd := data[5] args := data[6 : len(data)-32] return types.UserRequest{ Remote: types.ClientRemote{Addr: addr, Counter: counter}, Instruction: types.Instruction{Command: cmd, Arguments: args}, }, nil } func (t *UserTransport) send(req types.UserRequest) { buf := make([]byte, 5+len(req.Instruction.Arguments)) binary.BigEndian.PutUint32(buf[0:4], req.Remote.Counter) buf[4] = req.Instruction.Command copy(buf[5:], req.Instruction.Arguments) signed := crypto.SignData(buf, t.d.Storage.User.SecretKey) _ = t.c.WriteToUDPR(signed, req.Remote.Addr) } func (t *UserTransport) Send(req types.UserRequest) { t.w.enqueue(req) }