mirror of https://github.com/v2ray/v2ray-core
rename Error to Err
parent
5ee87404fd
commit
7f661f5215
|
@ -27,7 +27,7 @@ func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
|
|||
func (this *DefaultDispatcher) Initialize(space app.Space) error {
|
||||
if !space.HasApp(proxyman.APP_ID_OUTBOUND_MANAGER) {
|
||||
log.Error("DefaultDispatcher: OutboundHandlerManager is not found in the space.")
|
||||
return app.ErrorMissingApplication
|
||||
return app.ErrMissingApplication
|
||||
}
|
||||
this.ohm = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ func NewCacheServer(space app.Space, config *Config) *CacheServer {
|
|||
space.InitializeApplication(func() error {
|
||||
if !space.HasApp(dispatcher.APP_ID) {
|
||||
log.Error("DNS: Dispatcher is not found in the space.")
|
||||
return app.ErrorMissingApplication
|
||||
return app.ErrMissingApplication
|
||||
}
|
||||
|
||||
dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
|
||||
|
|
|
@ -9,7 +9,7 @@ type ConfigObjectCreator func([]byte) (interface{}, error)
|
|||
var (
|
||||
configCache map[string]ConfigObjectCreator
|
||||
|
||||
ErrorRouterNotFound = errors.New("Router not found.")
|
||||
ErrRouterNotFound = errors.New("Router not found.")
|
||||
)
|
||||
|
||||
func RegisterRouterConfig(strategy string, creator ConfigObjectCreator) error {
|
||||
|
@ -21,7 +21,7 @@ func RegisterRouterConfig(strategy string, creator ConfigObjectCreator) error {
|
|||
func CreateRouterConfig(strategy string, data []byte) (interface{}, error) {
|
||||
creator, found := configCache[strategy]
|
||||
if !found {
|
||||
return nil, ErrorRouterNotFound
|
||||
return nil, ErrRouterNotFound
|
||||
}
|
||||
return creator(data)
|
||||
}
|
||||
|
|
|
@ -33,5 +33,5 @@ func CreateRouter(name string, rawConfig interface{}, space app.Space) (Router,
|
|||
if factory, found := routerCache[name]; found {
|
||||
return factory.Create(rawConfig, space)
|
||||
}
|
||||
return nil, ErrorRouterNotFound
|
||||
return nil, ErrRouterNotFound
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorInvalidRule = errors.New("Invalid Rule")
|
||||
ErrorNoRuleApplicable = errors.New("No rule applicable")
|
||||
ErrInvalidRule = errors.New("Invalid Rule")
|
||||
ErrNoRuleApplicable = errors.New("No rule applicable")
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
|
@ -29,7 +29,7 @@ func NewRouter(config *RouterRuleConfig, space app.Space) *Router {
|
|||
space.InitializeApplication(func() error {
|
||||
if !space.HasApp(dns.APP_ID) {
|
||||
log.Error("DNS: Router is not found in the space.")
|
||||
return app.ErrorMissingApplication
|
||||
return app.ErrMissingApplication
|
||||
}
|
||||
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
|
||||
return nil
|
||||
|
@ -79,7 +79,7 @@ func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, erro
|
|||
}
|
||||
}
|
||||
|
||||
return "", ErrorNoRuleApplicable
|
||||
return "", ErrNoRuleApplicable
|
||||
}
|
||||
|
||||
func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorMissingApplication = errors.New("App: Failed to found one or more applications.")
|
||||
ErrMissingApplication = errors.New("App: Failed to found one or more applications.")
|
||||
)
|
||||
|
||||
type ID int
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
// ErrorInvalidPortRage indicates an error during port range parsing.
|
||||
ErrorInvalidPortRange = errors.New("Invalid port range.")
|
||||
// ErrInvalidPortRage indicates an error during port range parsing.
|
||||
ErrInvalidPortRange = errors.New("Invalid port range.")
|
||||
)
|
||||
|
||||
// Port represents a network port in TCP and UDP protocol.
|
||||
|
@ -25,7 +25,7 @@ func PortFromBytes(port []byte) Port {
|
|||
// @error when the integer is not positive or larger then 65535
|
||||
func PortFromInt(v int) (Port, error) {
|
||||
if v <= 0 || v > 65535 {
|
||||
return Port(0), ErrorInvalidPortRange
|
||||
return Port(0), ErrInvalidPortRange
|
||||
}
|
||||
return Port(v), nil
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ func PortFromInt(v int) (Port, error) {
|
|||
func PortFromString(s string) (Port, error) {
|
||||
v, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return Port(0), ErrorInvalidPortRange
|
||||
return Port(0), ErrInvalidPortRange
|
||||
}
|
||||
return PortFromInt(v)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func parseStringPort(data []byte) (Port, Port, error) {
|
|||
}
|
||||
pair := strings.SplitN(s, "-", 2)
|
||||
if len(pair) == 0 {
|
||||
return Port(0), Port(0), ErrorInvalidPortRange
|
||||
return Port(0), Port(0), ErrInvalidPortRange
|
||||
}
|
||||
if len(pair) == 1 {
|
||||
port, err := PortFromString(pair[0])
|
||||
|
@ -59,11 +59,11 @@ func (this *PortRange) UnmarshalJSON(data []byte) error {
|
|||
this.To = to
|
||||
if this.From > this.To {
|
||||
log.Error("Invalid port range ", this.From, " -> ", this.To)
|
||||
return ErrorInvalidPortRange
|
||||
return ErrInvalidPortRange
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Error("Invalid port range: ", string(data))
|
||||
return ErrorInvalidPortRange
|
||||
return ErrInvalidPortRange
|
||||
}
|
||||
|
|
|
@ -26,10 +26,10 @@ func TestOverRangeIntPort(t *testing.T) {
|
|||
|
||||
var portRange PortRange
|
||||
err := json.Unmarshal([]byte("70000"), &portRange)
|
||||
assert.Error(err).Equals(ErrorInvalidPortRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
|
||||
err = json.Unmarshal([]byte("-1"), &portRange)
|
||||
assert.Error(err).Equals(ErrorInvalidPortRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
}
|
||||
|
||||
func TestSingleStringPort(t *testing.T) {
|
||||
|
@ -59,14 +59,14 @@ func TestOverRangeStringPort(t *testing.T) {
|
|||
|
||||
var portRange PortRange
|
||||
err := json.Unmarshal([]byte("\"65536\""), &portRange)
|
||||
assert.Error(err).Equals(ErrorInvalidPortRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
|
||||
err = json.Unmarshal([]byte("\"70000-80000\""), &portRange)
|
||||
assert.Error(err).Equals(ErrorInvalidPortRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
|
||||
err = json.Unmarshal([]byte("\"1-90000\""), &portRange)
|
||||
assert.Error(err).Equals(ErrorInvalidPortRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
|
||||
err = json.Unmarshal([]byte("\"700-600\""), &portRange)
|
||||
assert.Error(err).Equals(ErrorInvalidPortRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorInvalidUser = errors.New("Invalid user.")
|
||||
ErrorInvalidVersion = errors.New("Invalid version.")
|
||||
ErrInvalidUser = errors.New("Invalid user.")
|
||||
ErrInvalidVersion = errors.New("Invalid version.")
|
||||
)
|
||||
|
|
|
@ -114,7 +114,7 @@ func (this *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Res
|
|||
|
||||
if buffer.Value[0] != this.responseHeader {
|
||||
log.Info("Raw: Unexpected response header. Expecting ", this.responseHeader, " but actually ", buffer.Value[0])
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
|
||||
header := &protocol.ResponseHeader{
|
||||
|
|
|
@ -13,14 +13,14 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorCommandTypeMismatch = errors.New("Command type mismatch.")
|
||||
ErrorUnknownCommand = errors.New("Unknown command.")
|
||||
ErrorCommandTooLarge = errors.New("Command too large.")
|
||||
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 ErrorUnknownCommand
|
||||
return ErrUnknownCommand
|
||||
}
|
||||
|
||||
var cmdId byte
|
||||
|
@ -30,7 +30,7 @@ func MarshalCommand(command interface{}, writer io.Writer) error {
|
|||
factory = new(CommandSwitchAccountFactory)
|
||||
cmdId = 1
|
||||
default:
|
||||
return ErrorUnknownCommand
|
||||
return ErrUnknownCommand
|
||||
}
|
||||
|
||||
buffer := alloc.NewSmallBuffer().Clear()
|
||||
|
@ -42,7 +42,7 @@ func MarshalCommand(command interface{}, writer io.Writer) error {
|
|||
auth := Authenticate(buffer.Value)
|
||||
len := buffer.Len() + 4
|
||||
if len > 255 {
|
||||
return ErrorCommandTooLarge
|
||||
return ErrCommandTooLarge
|
||||
}
|
||||
|
||||
writer.Write([]byte{cmdId, byte(len), byte(auth >> 24), byte(auth >> 16), byte(auth >> 8), byte(auth)})
|
||||
|
@ -52,12 +52,12 @@ func MarshalCommand(command interface{}, writer io.Writer) error {
|
|||
|
||||
func UnmarshalCommand(cmdId byte, data []byte) (protocol.ResponseCommand, error) {
|
||||
if len(data) <= 4 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
expectedAuth := Authenticate(data[4:])
|
||||
actualAuth := serial.BytesToUint32(data[:4])
|
||||
if expectedAuth != actualAuth {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
|
||||
var factory CommandFactory
|
||||
|
@ -65,7 +65,7 @@ func UnmarshalCommand(cmdId byte, data []byte) (protocol.ResponseCommand, error)
|
|||
case 1:
|
||||
factory = new(CommandSwitchAccountFactory)
|
||||
default:
|
||||
return nil, ErrorUnknownCommand
|
||||
return nil, ErrUnknownCommand
|
||||
}
|
||||
return factory.Unmarshal(data[4:])
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ type CommandSwitchAccountFactory struct {
|
|||
func (this *CommandSwitchAccountFactory) Marshal(command interface{}, writer io.Writer) error {
|
||||
cmd, ok := command.(*protocol.CommandSwitchAccount)
|
||||
if !ok {
|
||||
return ErrorCommandTypeMismatch
|
||||
return ErrCommandTypeMismatch
|
||||
}
|
||||
|
||||
hostStr := ""
|
||||
|
@ -109,38 +109,38 @@ func (this *CommandSwitchAccountFactory) Marshal(command interface{}, writer io.
|
|||
func (this *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) {
|
||||
cmd := new(protocol.CommandSwitchAccount)
|
||||
if len(data) == 0 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
lenHost := int(data[0])
|
||||
if len(data) < lenHost+1 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
if lenHost > 0 {
|
||||
cmd.Host = v2net.ParseAddress(string(data[1 : 1+lenHost]))
|
||||
}
|
||||
portStart := 1 + lenHost
|
||||
if len(data) < portStart+2 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
cmd.Port = v2net.PortFromBytes(data[portStart : portStart+2])
|
||||
idStart := portStart + 2
|
||||
if len(data) < idStart+16 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16])
|
||||
alterIdStart := idStart + 16
|
||||
if len(data) < alterIdStart+2 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
cmd.AlterIds = serial.BytesToUint16(data[alterIdStart : alterIdStart+2])
|
||||
levelStart := alterIdStart + 2
|
||||
if len(data) < levelStart+1 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
cmd.Level = protocol.UserLevel(data[levelStart])
|
||||
timeStart := levelStart + 1
|
||||
if len(data) < timeStart {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
cmd.ValidMin = data[timeStart]
|
||||
return cmd, nil
|
||||
|
|
|
@ -54,7 +54,7 @@ func (this *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Requ
|
|||
|
||||
user, timestamp, valid := this.userValidator.Get(buffer.Value[:protocol.IDBytesLen])
|
||||
if !valid {
|
||||
return nil, protocol.ErrorInvalidUser
|
||||
return nil, protocol.ErrInvalidUser
|
||||
}
|
||||
|
||||
timestampHash := md5.New()
|
||||
|
@ -78,7 +78,7 @@ func (this *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Requ
|
|||
|
||||
if request.Version != Version {
|
||||
log.Info("Raw: Invalid protocol version ", request.Version)
|
||||
return nil, protocol.ErrorInvalidVersion
|
||||
return nil, protocol.ErrInvalidVersion
|
||||
}
|
||||
|
||||
this.requestBodyIV = append([]byte(nil), buffer.Value[1:17]...) // 16 bytes
|
||||
|
@ -114,7 +114,7 @@ func (this *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Requ
|
|||
}
|
||||
domainLength := int(buffer.Value[41])
|
||||
if domainLength == 0 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
nBytes, err = io.ReadFull(decryptor, buffer.Value[42:42+domainLength])
|
||||
if err != nil {
|
||||
|
@ -138,7 +138,7 @@ func (this *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Requ
|
|||
expectedHash := serial.BytesToUint32(buffer.Value[bufferLen : bufferLen+4])
|
||||
|
||||
if actualHash != expectedHash {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
|
||||
return request, nil
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorRetryFailed = errors.New("All retry attempts failed.")
|
||||
ErrRetryFailed = errors.New("All retry attempts failed.")
|
||||
)
|
||||
|
||||
// Strategy is a way to retry on a specific function.
|
||||
|
@ -29,7 +29,7 @@ func (r *retryer) On(method func() error) error {
|
|||
}
|
||||
delay := r.NextDelay(attempt)
|
||||
if delay < 0 {
|
||||
return ErrorRetryFailed
|
||||
return ErrRetryFailed
|
||||
}
|
||||
<-time.After(time.Duration(delay) * time.Millisecond)
|
||||
attempt++
|
||||
|
|
|
@ -76,6 +76,6 @@ func TestRetryExhausted(t *testing.T) {
|
|||
})
|
||||
duration := time.Since(startTime)
|
||||
|
||||
assert.Error(err).Equals(ErrorRetryFailed)
|
||||
assert.Error(err).Equals(ErrRetryFailed)
|
||||
assert.Int64(int64(duration / time.Millisecond)).AtLeast(1900)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
var (
|
||||
byteGroups = []int{8, 4, 4, 4, 12}
|
||||
|
||||
ErrorInvalidID = errors.New("Invalid ID.")
|
||||
ErrInvalidID = errors.New("Invalid ID.")
|
||||
)
|
||||
|
||||
type UUID [16]byte
|
||||
|
@ -74,7 +74,7 @@ func New() *UUID {
|
|||
// PraseBytes converts an UUID in byte form to object.
|
||||
func ParseBytes(b []byte) (*UUID, error) {
|
||||
if len(b) != 16 {
|
||||
return nil, ErrorInvalidID
|
||||
return nil, ErrInvalidID
|
||||
}
|
||||
uuid := new(UUID)
|
||||
copy(uuid[:], b)
|
||||
|
@ -85,7 +85,7 @@ func ParseBytes(b []byte) (*UUID, error) {
|
|||
func ParseString(str string) (*UUID, error) {
|
||||
text := []byte(str)
|
||||
if len(text) < 32 {
|
||||
return nil, ErrorInvalidID
|
||||
return nil, ErrInvalidID
|
||||
}
|
||||
|
||||
uuid := new(UUID)
|
||||
|
|
|
@ -18,7 +18,7 @@ func TestParseBytes(t *testing.T) {
|
|||
assert.String(uuid.String()).Equals(str)
|
||||
|
||||
_, err = ParseBytes([]byte{1, 3, 2, 4})
|
||||
assert.Error(err).Equals(ErrorInvalidID)
|
||||
assert.Error(err).Equals(ErrInvalidID)
|
||||
}
|
||||
|
||||
func TestParseString(t *testing.T) {
|
||||
|
@ -32,7 +32,7 @@ func TestParseString(t *testing.T) {
|
|||
assert.Bytes(uuid.Bytes()).Equals(expectedBytes)
|
||||
|
||||
uuid, err = ParseString("2418d087")
|
||||
assert.Error(err).Equals(ErrorInvalidID)
|
||||
assert.Error(err).Equals(ErrInvalidID)
|
||||
|
||||
uuid, err = ParseString("2418d087-648k-4990-86e8-19dca1d006d3")
|
||||
assert.Error(err).IsNotNil()
|
||||
|
|
|
@ -39,7 +39,7 @@ func NewDokodemoDoor(config *Config, space app.Space, meta *proxy.InboundHandler
|
|||
space.InitializeApplication(func() error {
|
||||
if !space.HasApp(dispatcher.APP_ID) {
|
||||
log.Error("Dokodemo: Dispatcher is not found in the space.")
|
||||
return app.ErrorMissingApplication
|
||||
return app.ErrMissingApplication
|
||||
}
|
||||
d.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
|
||||
return nil
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorInvalidAuthentication = errors.New("Invalid authentication.")
|
||||
ErrorInvalidProtocolVersion = errors.New("Invalid protocol version.")
|
||||
ErrorAlreadyListening = errors.New("Already listening on another port.")
|
||||
ErrInvalidAuthentication = errors.New("Invalid authentication.")
|
||||
ErrInvalidProtocolVersion = errors.New("Invalid protocol version.")
|
||||
ErrAlreadyListening = errors.New("Already listening on another port.")
|
||||
)
|
||||
|
|
|
@ -36,7 +36,7 @@ func NewFreedomConnection(config *Config, space app.Space, meta *proxy.OutboundH
|
|||
if config.DomainStrategy == DomainStrategyUseIP {
|
||||
if !space.HasApp(dns.APP_ID) {
|
||||
log.Error("Freedom: DNS server is not found in the space.")
|
||||
return app.ErrorMissingApplication
|
||||
return app.ErrMissingApplication
|
||||
}
|
||||
f.dns = space.GetApp(dns.APP_ID).(dns.Server)
|
||||
}
|
||||
|
|
|
@ -272,7 +272,7 @@ func (this *ServerFactory) StreamCapability() internet.StreamConnectionType {
|
|||
|
||||
func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
|
||||
if !space.HasApp(dispatcher.APP_ID) {
|
||||
return nil, internal.ErrorBadConfiguration
|
||||
return nil, internal.ErrBadConfiguration
|
||||
}
|
||||
return NewServer(
|
||||
rawConfig.(*Config),
|
||||
|
|
|
@ -12,14 +12,14 @@ var (
|
|||
inboundFactories = make(map[string]InboundHandlerFactory)
|
||||
outboundFactories = make(map[string]OutboundHandlerFactory)
|
||||
|
||||
ErrorProxyNotFound = errors.New("Proxy not found.")
|
||||
ErrorNameExists = errors.New("Proxy with the same name already exists.")
|
||||
ErrorBadConfiguration = errors.New("Bad proxy configuration.")
|
||||
ErrProxyNotFound = errors.New("Proxy not found.")
|
||||
ErrNameExists = errors.New("Proxy with the same name already exists.")
|
||||
ErrBadConfiguration = errors.New("Bad proxy configuration.")
|
||||
)
|
||||
|
||||
func RegisterInboundHandlerCreator(name string, creator InboundHandlerFactory) error {
|
||||
if _, found := inboundFactories[name]; found {
|
||||
return ErrorNameExists
|
||||
return ErrNameExists
|
||||
}
|
||||
inboundFactories[name] = creator
|
||||
return nil
|
||||
|
@ -33,7 +33,7 @@ func MustRegisterInboundHandlerCreator(name string, creator InboundHandlerFactor
|
|||
|
||||
func RegisterOutboundHandlerCreator(name string, creator OutboundHandlerFactory) error {
|
||||
if _, found := outboundFactories[name]; found {
|
||||
return ErrorNameExists
|
||||
return ErrNameExists
|
||||
}
|
||||
outboundFactories[name] = creator
|
||||
return nil
|
||||
|
@ -48,7 +48,7 @@ func MustRegisterOutboundHandlerCreator(name string, creator OutboundHandlerFact
|
|||
func CreateInboundHandler(name string, space app.Space, rawConfig []byte, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
|
||||
creator, found := inboundFactories[name]
|
||||
if !found {
|
||||
return nil, ErrorProxyNotFound
|
||||
return nil, ErrProxyNotFound
|
||||
}
|
||||
if meta.StreamSettings == nil {
|
||||
meta.StreamSettings = &internet.StreamSettings{
|
||||
|
@ -71,7 +71,7 @@ func CreateInboundHandler(name string, space app.Space, rawConfig []byte, meta *
|
|||
func CreateOutboundHandler(name string, space app.Space, rawConfig []byte, meta *proxy.OutboundHandlerMeta) (proxy.OutboundHandler, error) {
|
||||
creator, found := outboundFactories[name]
|
||||
if !found {
|
||||
return nil, ErrorProxyNotFound
|
||||
return nil, ErrProxyNotFound
|
||||
}
|
||||
if meta.StreamSettings == nil {
|
||||
meta.StreamSettings = &internet.StreamSettings{
|
||||
|
|
|
@ -46,12 +46,12 @@ func (this *Config) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
default:
|
||||
log.Error("Shadowsocks: Unknown cipher method: ", jsonConfig.Cipher)
|
||||
return internal.ErrorBadConfiguration
|
||||
return internal.ErrBadConfiguration
|
||||
}
|
||||
|
||||
if len(jsonConfig.Password) == 0 {
|
||||
log.Error("Shadowsocks: Password is not specified.")
|
||||
return internal.ErrorBadConfiguration
|
||||
return internal.ErrBadConfiguration
|
||||
}
|
||||
this.Key = PasswordToCipherKey(jsonConfig.Password, this.Cipher.KeySize())
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ func (this *ChunkReader) Read() (*alloc.Buffer, error) {
|
|||
if !bytes.Equal(authBytes, actualAuthBytes) {
|
||||
buffer.Release()
|
||||
log.Debug("AuthenticationReader: Unexpected auth: ", authBytes)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
buffer.Value = payload
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, err
|
|||
if err != nil {
|
||||
if err != io.EOF {
|
||||
log.Warning("Shadowsocks: Failed to read address type: ", err)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, err
|
|||
_, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+4])
|
||||
if err != nil {
|
||||
log.Warning("Shadowsocks: Failed to read IPv4 address: ", err)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
request.Address = v2net.IPAddress(buffer.Value[lenBuffer : lenBuffer+4])
|
||||
lenBuffer += 4
|
||||
|
@ -70,7 +70,7 @@ func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, err
|
|||
_, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+16])
|
||||
if err != nil {
|
||||
log.Warning("Shadowsocks: Failed to read IPv6 address: ", err)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
request.Address = v2net.IPAddress(buffer.Value[lenBuffer : lenBuffer+16])
|
||||
lenBuffer += 16
|
||||
|
@ -78,26 +78,26 @@ func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, err
|
|||
_, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+1])
|
||||
if err != nil {
|
||||
log.Warning("Shadowsocks: Failed to read domain lenth: ", err)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
domainLength := int(buffer.Value[lenBuffer])
|
||||
lenBuffer++
|
||||
_, err = io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+domainLength])
|
||||
if err != nil {
|
||||
log.Warning("Shadowsocks: Failed to read domain: ", err)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
request.Address = v2net.DomainAddress(string(buffer.Value[lenBuffer : lenBuffer+domainLength]))
|
||||
lenBuffer += domainLength
|
||||
default:
|
||||
log.Warning("Shadowsocks: Unknown address type: ", addrType)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
|
||||
_, err = io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+2])
|
||||
if err != nil {
|
||||
log.Warning("Shadowsocks: Failed to read port: ", err)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
|
||||
request.Port = v2net.PortFromBytes(buffer.Value[lenBuffer : lenBuffer+2])
|
||||
|
@ -109,7 +109,7 @@ func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, err
|
|||
nBytes, err := reader.Read(buffer.Value[lenBuffer:])
|
||||
if err != nil {
|
||||
log.Warning("Shadowsocks: Failed to read UDP payload: ", err)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
buffer.Slice(0, lenBuffer+nBytes)
|
||||
if request.OTA {
|
||||
|
@ -125,7 +125,7 @@ func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, err
|
|||
_, err = io.ReadFull(reader, authBytes)
|
||||
if err != nil {
|
||||
log.Warning("Shadowsocks: Failed to read OTA: ", err)
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, err
|
|||
actualAuth := auth.Authenticate(nil, buffer.Value[0:lenBuffer])
|
||||
if !bytes.Equal(actualAuth, authBytes) {
|
||||
log.Warning("Shadowsocks: Invalid OTA.")
|
||||
return nil, proxy.ErrorInvalidAuthentication
|
||||
return nil, proxy.ErrInvalidAuthentication
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ func TestSingleBytePayload(t *testing.T) {
|
|||
|
||||
buffer := alloc.NewSmallBuffer().Clear().AppendBytes(1)
|
||||
_, err := ReadRequest(buffer, nil, false)
|
||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
||||
assert.Error(err).Equals(transport.ErrCorruptedPacket)
|
||||
}
|
||||
|
||||
func TestWrongAddressType(t *testing.T) {
|
||||
|
@ -46,7 +46,7 @@ func TestWrongAddressType(t *testing.T) {
|
|||
|
||||
buffer := alloc.NewSmallBuffer().Clear().AppendBytes(5)
|
||||
_, err := ReadRequest(buffer, nil, false)
|
||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
||||
assert.Error(err).Equals(transport.ErrCorruptedPacket)
|
||||
}
|
||||
|
||||
func TestInsufficientAddressRequest(t *testing.T) {
|
||||
|
@ -54,15 +54,15 @@ func TestInsufficientAddressRequest(t *testing.T) {
|
|||
|
||||
buffer := alloc.NewSmallBuffer().Clear().AppendBytes(1, 1)
|
||||
_, err := ReadRequest(buffer, nil, false)
|
||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
||||
assert.Error(err).Equals(transport.ErrCorruptedPacket)
|
||||
|
||||
buffer = alloc.NewSmallBuffer().Clear().AppendBytes(4, 1)
|
||||
_, err = ReadRequest(buffer, nil, false)
|
||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
||||
assert.Error(err).Equals(transport.ErrCorruptedPacket)
|
||||
|
||||
buffer = alloc.NewSmallBuffer().Clear().AppendBytes(3, 255, 1)
|
||||
_, err = ReadRequest(buffer, nil, false)
|
||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
||||
assert.Error(err).Equals(transport.ErrCorruptedPacket)
|
||||
}
|
||||
|
||||
func TestInsufficientPortRequest(t *testing.T) {
|
||||
|
@ -70,7 +70,7 @@ func TestInsufficientPortRequest(t *testing.T) {
|
|||
|
||||
buffer := alloc.NewSmallBuffer().Clear().AppendBytes(1, 1, 2, 3, 4, 5)
|
||||
_, err := ReadRequest(buffer, nil, false)
|
||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
||||
assert.Error(err).Equals(transport.ErrCorruptedPacket)
|
||||
}
|
||||
|
||||
func TestOTARequest(t *testing.T) {
|
||||
|
@ -98,7 +98,7 @@ func TestInvalidOTARequest(t *testing.T) {
|
|||
[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5},
|
||||
[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5}))
|
||||
_, err := ReadRequest(buffer, auth, false)
|
||||
assert.Error(err).Equals(proxy.ErrorInvalidAuthentication)
|
||||
assert.Error(err).Equals(proxy.ErrInvalidAuthentication)
|
||||
}
|
||||
|
||||
func TestUDPRequestParsing(t *testing.T) {
|
||||
|
|
|
@ -257,7 +257,7 @@ func (this *ServerFactory) StreamCapability() internet.StreamConnectionType {
|
|||
|
||||
func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
|
||||
if !space.HasApp(dispatcher.APP_ID) {
|
||||
return nil, internal.ErrorBadConfiguration
|
||||
return nil, internal.ErrBadConfiguration
|
||||
}
|
||||
return NewServer(
|
||||
rawConfig.(*Config),
|
||||
|
|
|
@ -39,7 +39,7 @@ func (this *Config) UnmarshalJSON(data []byte) error {
|
|||
this.AuthType = AuthTypePassword
|
||||
} else {
|
||||
log.Error("Socks: Unknown auth method: ", rawConfig.AuthMethod)
|
||||
return internal.ErrorBadConfiguration
|
||||
return internal.ErrBadConfiguration
|
||||
}
|
||||
|
||||
if len(rawConfig.Accounts) > 0 {
|
||||
|
|
|
@ -49,7 +49,7 @@ func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, aut
|
|||
}
|
||||
if nBytes < 2 {
|
||||
log.Warning("Socks: expected 2 bytes read, but only ", nBytes, " bytes read")
|
||||
err = transport.ErrorCorruptedPacket
|
||||
err = transport.ErrCorruptedPacket
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -65,20 +65,20 @@ func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, aut
|
|||
auth.version = buffer.Value[0]
|
||||
if auth.version != socksVersion {
|
||||
log.Warning("Socks: Unknown protocol version ", auth.version)
|
||||
err = proxy.ErrorInvalidProtocolVersion
|
||||
err = proxy.ErrInvalidProtocolVersion
|
||||
return
|
||||
}
|
||||
|
||||
auth.nMethods = buffer.Value[1]
|
||||
if auth.nMethods <= 0 {
|
||||
log.Warning("Socks: Zero length of authentication methods")
|
||||
err = proxy.ErrorInvalidAuthentication
|
||||
err = proxy.ErrInvalidAuthentication
|
||||
return
|
||||
}
|
||||
|
||||
if nBytes-2 != int(auth.nMethods) {
|
||||
log.Warning("Socks: Unmatching number of auth methods, expecting ", auth.nMethods, ", but got ", nBytes)
|
||||
err = proxy.ErrorInvalidAuthentication
|
||||
err = proxy.ErrInvalidAuthentication
|
||||
return
|
||||
}
|
||||
copy(auth.authMethods[:], buffer.Value[2:nBytes])
|
||||
|
@ -226,7 +226,7 @@ func ReadRequest(reader io.Reader) (request *Socks5Request, err error) {
|
|||
}
|
||||
default:
|
||||
log.Warning("Socks: Unexpected address type ", request.AddrType)
|
||||
err = transport.ErrorCorruptedPacket
|
||||
err = transport.ErrCorruptedPacket
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ func TestSingleByteAuthRequest(t *testing.T) {
|
|||
assert := assert.On(t)
|
||||
|
||||
_, _, err := ReadAuthentication(bytes.NewReader(make([]byte, 1)))
|
||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
||||
assert.Error(err).Equals(transport.ErrCorruptedPacket)
|
||||
}
|
||||
|
||||
func TestZeroAuthenticationMethod(t *testing.T) {
|
||||
|
@ -144,14 +144,14 @@ func TestZeroAuthenticationMethod(t *testing.T) {
|
|||
|
||||
buffer := alloc.NewBuffer().Clear().AppendBytes(5, 0)
|
||||
_, _, err := ReadAuthentication(buffer)
|
||||
assert.Error(err).Equals(proxy.ErrorInvalidAuthentication)
|
||||
assert.Error(err).Equals(proxy.ErrInvalidAuthentication)
|
||||
}
|
||||
func TestWrongProtocolVersion(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
buffer := alloc.NewBuffer().Clear().AppendBytes(6, 1, 0)
|
||||
_, _, err := ReadAuthentication(buffer)
|
||||
assert.Error(err).Equals(proxy.ErrorInvalidProtocolVersion)
|
||||
assert.Error(err).Equals(proxy.ErrInvalidProtocolVersion)
|
||||
}
|
||||
|
||||
func TestEmptyRequest(t *testing.T) {
|
||||
|
|
|
@ -40,7 +40,7 @@ func (request *Socks5UDPRequest) Write(buffer *alloc.Buffer) {
|
|||
|
||||
func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) {
|
||||
if len(packet) < 5 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
request := new(Socks5UDPRequest)
|
||||
|
||||
|
@ -53,7 +53,7 @@ func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) {
|
|||
switch addrType {
|
||||
case AddrTypeIPv4:
|
||||
if len(packet) < 10 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
ip := packet[4:8]
|
||||
request.Port = v2net.PortFromBytes(packet[8:10])
|
||||
|
@ -61,7 +61,7 @@ func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) {
|
|||
dataBegin = 10
|
||||
case AddrTypeIPv6:
|
||||
if len(packet) < 22 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
ip := packet[4:20]
|
||||
request.Port = v2net.PortFromBytes(packet[20:22])
|
||||
|
@ -70,7 +70,7 @@ func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) {
|
|||
case AddrTypeDomain:
|
||||
domainLength := int(packet[4])
|
||||
if len(packet) < 5+domainLength+2 {
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
domain := string(packet[5 : 5+domainLength])
|
||||
request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2])
|
||||
|
|
|
@ -15,7 +15,7 @@ func TestSingleByteUDPRequest(t *testing.T) {
|
|||
if request != nil {
|
||||
t.Fail()
|
||||
}
|
||||
assert.Error(err).Equals(transport.ErrorCorruptedPacket)
|
||||
assert.Error(err).Equals(transport.ErrCorruptedPacket)
|
||||
}
|
||||
|
||||
func TestDomainAddressRequest(t *testing.T) {
|
||||
|
|
|
@ -163,8 +163,8 @@ func (this *Server) handleSocks5(clientAddr string, reader *v2io.BufferedReader,
|
|||
}
|
||||
if status != byte(0) {
|
||||
log.Warning("Socks: Invalid user account: ", upRequest.AuthDetail())
|
||||
log.Access(clientAddr, "", log.AccessRejected, proxy.ErrorInvalidAuthentication)
|
||||
return proxy.ErrorInvalidAuthentication
|
||||
log.Access(clientAddr, "", log.AccessRejected, proxy.ErrInvalidAuthentication)
|
||||
return proxy.ErrInvalidAuthentication
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ func (this *ServerFactory) StreamCapability() internet.StreamConnectionType {
|
|||
|
||||
func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
|
||||
if !space.HasApp(dispatcher.APP_ID) {
|
||||
return nil, internal.ErrorBadConfiguration
|
||||
return nil, internal.ErrBadConfiguration
|
||||
}
|
||||
return NewServer(
|
||||
rawConfig.(*Config),
|
||||
|
|
|
@ -17,7 +17,7 @@ func RegisterInboundConnectionHandlerCreator(prefix string, creator internal.Inb
|
|||
for {
|
||||
name := prefix + randomString()
|
||||
err := internal.RegisterInboundHandlerCreator(name, creator)
|
||||
if err != internal.ErrorNameExists {
|
||||
if err != internal.ErrNameExists {
|
||||
return name, err
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func RegisterOutboundConnectionHandlerCreator(prefix string, creator internal.Ou
|
|||
for {
|
||||
name := prefix + randomString()
|
||||
err := internal.RegisterOutboundHandlerCreator(name, creator)
|
||||
if err != internal.ErrorNameExists {
|
||||
if err != internal.ErrNameExists {
|
||||
return name, err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,7 +244,7 @@ func (this *Factory) StreamCapability() internet.StreamConnectionType {
|
|||
|
||||
func (this *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
|
||||
if !space.HasApp(dispatcher.APP_ID) {
|
||||
return nil, internal.ErrorBadConfiguration
|
||||
return nil, internal.ErrBadConfiguration
|
||||
}
|
||||
config := rawConfig.(*Config)
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ func (this *AuthChunkReader) Read() (*alloc.Buffer, error) {
|
|||
this.validator.Consume(buffer.Value[:this.chunkLength])
|
||||
if !this.validator.Validate() {
|
||||
buffer.Release()
|
||||
return nil, transport.ErrorCorruptedPacket
|
||||
return nil, transport.ErrCorruptedPacket
|
||||
}
|
||||
leftLength := buffer.Len() - this.chunkLength
|
||||
if leftLength > 0 {
|
||||
|
|
|
@ -21,7 +21,7 @@ func (this *Config) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
if len(rawOutbound.Receivers) == 0 {
|
||||
log.Error("VMessOut: 0 VMess receiver configured.")
|
||||
return internal.ErrorBadConfiguration
|
||||
return internal.ErrBadConfiguration
|
||||
}
|
||||
this.Receivers = rawOutbound.Receivers
|
||||
return nil
|
||||
|
|
|
@ -24,12 +24,12 @@ func (this *Receiver) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
if len(rawConfig.Users) == 0 {
|
||||
log.Error("VMess: 0 user configured for VMess outbound.")
|
||||
return internal.ErrorBadConfiguration
|
||||
return internal.ErrBadConfiguration
|
||||
}
|
||||
this.Accounts = rawConfig.Users
|
||||
if rawConfig.Address == nil {
|
||||
log.Error("VMess: Address is not set in VMess outbound config.")
|
||||
return internal.ErrorBadConfiguration
|
||||
return internal.ErrBadConfiguration
|
||||
}
|
||||
if rawConfig.Address.Address.String() == string([]byte{118, 50, 114, 97, 121, 46, 99, 111, 111, 108}) {
|
||||
rawConfig.Address.Address = v2net.IPAddress(serial.Uint32ToBytes(2891346854, nil))
|
||||
|
|
|
@ -5,5 +5,5 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorCorruptedPacket = errors.New("Packet is corrupted.")
|
||||
ErrCorruptedPacket = errors.New("Packet is corrupted.")
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorClosedConnection = errors.New("Connection already closed.")
|
||||
ErrClosedConnection = errors.New("Connection already closed.")
|
||||
|
||||
KCPListenFunc ListenFunc
|
||||
TCPListenFunc ListenFunc
|
||||
|
|
|
@ -14,7 +14,7 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorIOTimeout = errors.New("IO Timeout")
|
||||
ErrIOTimeout = errors.New("IO Timeout")
|
||||
)
|
||||
|
||||
// NewRay creates a new Ray for direct traffic transport.
|
||||
|
@ -82,7 +82,7 @@ func (this *Stream) Write(data *alloc.Buffer) error {
|
|||
}
|
||||
for {
|
||||
err := this.TryWriteOnce(data)
|
||||
if err != ErrorIOTimeout {
|
||||
if err != ErrIOTimeout {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ func (this *Stream) TryWriteOnce(data *alloc.Buffer) error {
|
|||
case this.buffer <- data:
|
||||
return nil
|
||||
case <-time.After(2 * time.Second):
|
||||
return ErrorIOTimeout
|
||||
return ErrIOTimeout
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue