package transport import ( "encoding/binary" "net" "ripple/crypto" "ripple/state" "ripple/types" "ripple/udpr" ) type UserTransport struct { st *state.State w *senderWorker } func NewUserTransport(conn *udpr.UDPRConn, st *state.State) *UserTransport { return &UserTransport{ st: st, w: newSenderWorker(conn), } } 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.st.Storage.User.SecretKey) { return types.UserRequest{}, errInvalidUserRequest } counter := binary.BigEndian.Uint32(data[1:5]) if counter <= t.st.Storage.User.Counter { return types.UserRequest{}, errInvalidUserRequest } if err := t.st.SetUserCounter(counter); err != nil { return types.UserRequest{}, err } return types.UserRequest{ Remote: types.ClientRemote{ Addr: addr, Counter: counter, }, Instruction: types.Instruction{ Command: data[5], Arguments: data[6 : len(data)-32], }, }, 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.st.Storage.User.SecretKey) t.w.enqueue(sendRequest{ data: signed, dest: req.Remote.Addr, }) }