| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- package encoding
- import (
- "encoding/binary"
- "io"
- "github.com/xtls/xray-core/common"
- "github.com/xtls/xray-core/common/buf"
- "github.com/xtls/xray-core/common/errors"
- "github.com/xtls/xray-core/common/protocol"
- )
- var (
- ErrCommandTooLarge = errors.New("Command too large.")
- ErrCommandTypeMismatch = errors.New("Command type mismatch.")
- ErrInvalidAuth = errors.New("Invalid auth.")
- ErrInsufficientLength = errors.New("Insufficient length.")
- ErrUnknownCommand = errors.New("Unknown command.")
- )
- func MarshalCommand(command interface{}, writer io.Writer) error {
- if command == nil {
- return ErrUnknownCommand
- }
- var cmdID byte
- var factory CommandFactory
- switch command.(type) {
- default:
- return ErrUnknownCommand
- }
- buffer := buf.New()
- defer buffer.Release()
- err := factory.Marshal(command, buffer)
- if err != nil {
- return err
- }
- auth := Authenticate(buffer.Bytes())
- length := buffer.Len() + 4
- if length > 255 {
- return ErrCommandTooLarge
- }
- common.Must2(writer.Write([]byte{cmdID, byte(length), byte(auth >> 24), byte(auth >> 16), byte(auth >> 8), byte(auth)}))
- common.Must2(writer.Write(buffer.Bytes()))
- return nil
- }
- func UnmarshalCommand(cmdID byte, data []byte) (protocol.ResponseCommand, error) {
- if len(data) <= 4 {
- return nil, ErrInsufficientLength
- }
- expectedAuth := Authenticate(data[4:])
- actualAuth := binary.BigEndian.Uint32(data[:4])
- if expectedAuth != actualAuth {
- return nil, ErrInvalidAuth
- }
- var factory CommandFactory
- switch cmdID {
- default:
- return nil, ErrUnknownCommand
- }
- return factory.Unmarshal(data[4:])
- }
- type CommandFactory interface {
- Marshal(command interface{}, writer io.Writer) error
- Unmarshal(data []byte) (interface{}, error)
- }
|