| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 | package encodingimport (	"io"	"v2ray.com/core/common/buf"	"v2ray.com/core/common/errors"	v2net "v2ray.com/core/common/net"	"v2ray.com/core/common/protocol"	"v2ray.com/core/common/serial"	"v2ray.com/core/common/uuid")var (	ErrCommandTypeMismatch = errors.New("Command type mismatch.")	ErrUnknownCommand      = errors.New("Unknown command.")	ErrCommandTooLarge     = errors.New("Command too large."))func MarshalCommand(command interface{}, writer io.Writer) error {	if command == nil {		return ErrUnknownCommand	}	var cmdId byte	var factory CommandFactory	switch command.(type) {	case *protocol.CommandSwitchAccount:		factory = new(CommandSwitchAccountFactory)		cmdId = 1	default:		return ErrUnknownCommand	}	buffer := buf.NewLocalBuffer(512)	defer buffer.Release()	err := factory.Marshal(command, buffer)	if err != nil {		return err	}	auth := Authenticate(buffer.Bytes())	len := buffer.Len() + 4	if len > 255 {		return ErrCommandTooLarge	}	writer.Write([]byte{cmdId, byte(len), byte(auth >> 24), byte(auth >> 16), byte(auth >> 8), byte(auth)})	writer.Write(buffer.Bytes())	return nil}func UnmarshalCommand(cmdId byte, data []byte) (protocol.ResponseCommand, error) {	if len(data) <= 4 {		return nil, errors.New("VMess|Command: Insufficient length.")	}	expectedAuth := Authenticate(data[4:])	actualAuth := serial.BytesToUint32(data[:4])	if expectedAuth != actualAuth {		return nil, errors.New("VMess|Command: Invalid auth.")	}	var factory CommandFactory	switch cmdId {	case 1:		factory = new(CommandSwitchAccountFactory)	default:		return nil, ErrUnknownCommand	}	return factory.Unmarshal(data[4:])}type CommandFactory interface {	Marshal(command interface{}, writer io.Writer) error	Unmarshal(data []byte) (interface{}, error)}type CommandSwitchAccountFactory struct {}func (v *CommandSwitchAccountFactory) Marshal(command interface{}, writer io.Writer) error {	cmd, ok := command.(*protocol.CommandSwitchAccount)	if !ok {		return ErrCommandTypeMismatch	}	hostStr := ""	if cmd.Host != nil {		hostStr = cmd.Host.String()	}	writer.Write([]byte{byte(len(hostStr))})	if len(hostStr) > 0 {		writer.Write([]byte(hostStr))	}	writer.Write(cmd.Port.Bytes(nil))	idBytes := cmd.ID.Bytes()	writer.Write(idBytes)	writer.Write(serial.Uint16ToBytes(cmd.AlterIds, nil))	writer.Write([]byte{byte(cmd.Level)})	writer.Write([]byte{cmd.ValidMin})	return nil}func (v *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) {	cmd := new(protocol.CommandSwitchAccount)	if len(data) == 0 {		return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.")	}	lenHost := int(data[0])	if len(data) < lenHost+1 {		return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.")	}	if lenHost > 0 {		cmd.Host = v2net.ParseAddress(string(data[1 : 1+lenHost]))	}	portStart := 1 + lenHost	if len(data) < portStart+2 {		return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.")	}	cmd.Port = v2net.PortFromBytes(data[portStart : portStart+2])	idStart := portStart + 2	if len(data) < idStart+16 {		return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.")	}	cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16])	alterIdStart := idStart + 16	if len(data) < alterIdStart+2 {		return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.")	}	cmd.AlterIds = serial.BytesToUint16(data[alterIdStart : alterIdStart+2])	levelStart := alterIdStart + 2	if len(data) < levelStart+1 {		return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.")	}	cmd.Level = uint32(data[levelStart])	timeStart := levelStart + 1	if len(data) < timeStart {		return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.")	}	cmd.ValidMin = data[timeStart]	return cmd, nil}
 |