Jelajahi Sumber

refactor error interface

Darien Raymond 8 tahun lalu
induk
melakukan
fc31f9b94c

+ 3 - 3
app/dispatcher/impl/default.go

@@ -58,13 +58,13 @@ func (v *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
 	if v.router != nil {
 		if tag, err := v.router.TakeDetour(ctx); err == nil {
 			if handler := v.ohm.GetHandler(tag); handler != nil {
-				log.Info("DefaultDispatcher: Taking detour [", tag, "] for [", destination, "].")
+				log.Trace(errors.New("taking detour [", tag, "] for [", destination, "]").Path("App", "Dispatcher", "Default"))
 				dispatcher = handler
 			} else {
-				log.Warning("DefaultDispatcher: Nonexisting tag: ", tag)
+				log.Trace(errors.New("nonexisting tag: ", tag).AtWarning().Path("App", "Dispatcher", "Default"))
 			}
 		} else {
-			log.Info("DefaultDispatcher: Default route for ", destination)
+			log.Trace(errors.New("default route for ", destination).Path("App", "Dispatcher", "Default"))
 		}
 	}
 

+ 2 - 1
app/dns/server/nameserver.go

@@ -11,6 +11,7 @@ import (
 	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/dice"
+	"v2ray.com/core/common/errors"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet/udp"
 )
@@ -200,7 +201,7 @@ func (v *LocalNameServer) QueryA(domain string) <-chan *ARecord {
 
 		ips, err := net.LookupIP(domain)
 		if err != nil {
-			log.Info("DNS: Failed to lookup IPs for domain ", domain)
+			log.Trace(errors.New("failed to lookup IPs for domain ", domain).Path("App", "DNS").Base(err))
 			return
 		}
 

+ 1 - 1
app/log/access.go

@@ -21,7 +21,7 @@ var (
 func InitAccessLogger(file string) error {
 	logger, err := internal.NewFileLogWriter(file)
 	if err != nil {
-		return errors.Base(err).Message("Failed to create access logger on file: ", file)
+		return errors.New("Failed to create access logger on file: ", file).Base(err).Path("App", "Log")
 	}
 	accessLoggerInstance = logger
 	return nil

+ 17 - 1
app/log/log.go

@@ -43,7 +43,7 @@ func SetLogLevel(level LogLevel) {
 func InitErrorLogger(file string) error {
 	logger, err := internal.NewFileLogWriter(file)
 	if err != nil {
-		return errors.Base(err).Message("Log: Failed to create error logger on file (", file, ")")
+		return errors.New("failed to create error logger on file (", file, ")").Base(err).Path("App", "Log")
 	}
 	streamLoggerInstance = logger
 	return nil
@@ -81,6 +81,22 @@ func Error(val ...interface{}) {
 	})
 }
 
+func Trace(err error) {
+	s := errors.GetSeverity(err)
+	switch s {
+	case errors.SeverityDebug:
+		Debug(err)
+	case errors.SeverityInfo:
+		Info(err)
+	case errors.SeverityWarning:
+		Warning(err)
+	case errors.SeverityError:
+		Error(err)
+	default:
+		Info(err)
+	}
+}
+
 type Instance struct {
 	config *Config
 }

+ 2 - 12
app/proxyman/inbound/worker.go

@@ -54,12 +54,7 @@ func (w *tcpWorker) callback(conn internet.Connection) {
 	ctx = proxy.ContextWithInboundEntryPoint(ctx, v2net.TCPDestination(w.address, w.port))
 	ctx = proxy.ContextWithSource(ctx, v2net.DestinationFromAddr(conn.RemoteAddr()))
 	if err := w.proxy.Process(ctx, v2net.Network_TCP, conn, w.dispatcher); err != nil {
-		err := errors.Base(err).Message("Proxyman|TCPWorker: Connection ends.")
-		if errors.IsActionRequired(err) {
-			log.Warning(err)
-		} else {
-			log.Info(err)
-		}
+		log.Trace(errors.New("connection ends").Base(err).Path("Proxyman", "TCPWorker"))
 	}
 	cancel()
 	conn.Close()
@@ -243,12 +238,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source v2net.Destination, originalDe
 			ctx = proxy.ContextWithSource(ctx, source)
 			ctx = proxy.ContextWithInboundEntryPoint(ctx, v2net.UDPDestination(w.address, w.port))
 			if err := w.proxy.Process(ctx, v2net.Network_UDP, conn, w.dispatcher); err != nil {
-				err = errors.Base(err).Message("Proxyman|UDPWorker: Connection ends.")
-				if errors.IsActionRequired(err) {
-					log.Warning(err)
-				} else {
-					log.Info(err)
-				}
+				log.Trace(errors.New("connection ends").Base(err).Path("Proxymann|UDPWorker"))
 			}
 			w.removeConn(source)
 			cancel()

+ 1 - 1
app/proxyman/mux/mux.go

@@ -83,7 +83,7 @@ func (m *ClientManager) Dispatch(ctx context.Context, outboundRay ray.OutboundRa
 
 	client, err := NewClient(m.proxy, m.dialer, m)
 	if err != nil {
-		return errors.Base(err).Message("Proxyman|Mux|ClientManager: Failed to create client.")
+		return errors.New("failed to create client").Base(err).Path("Proxymann", "Mux", "ClientManager")
 	}
 	m.clients = append(m.clients, client)
 	client.Dispatch(ctx, outboundRay)

+ 3 - 13
app/proxyman/outbound/handler.go

@@ -73,23 +73,13 @@ func (h *Handler) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) {
 	if h.mux != nil {
 		err := h.mux.Dispatch(ctx, outboundRay)
 		if err != nil {
-			err = errors.Base(err).Message("Proxyman|OutboundHandler: Failed to process outbound traffic.")
-			if errors.IsActionRequired(err) {
-				log.Warning(err)
-			} else {
-				log.Info(err)
-			}
+			log.Trace(errors.New("failed to process outbound traffic").Base(err).Path("Proxyman", "OutboundHandler"))
 		}
 	} else {
 		err := h.proxy.Process(ctx, outboundRay, h)
 		// Ensure outbound ray is properly closed.
 		if err != nil && errors.Cause(err) != io.EOF {
-			err = errors.Base(err).Message("Proxyman|OutboundHandler: Failed to process outbound traffic.")
-			if errors.IsActionRequired(err) {
-				log.Warning(err)
-			} else {
-				log.Info(err)
-			}
+			log.Trace(errors.New("failed to process outbound traffic").Base(err).Path("Proxyman", "OutboundHandler"))
 			outboundRay.OutboundOutput().CloseError()
 		} else {
 			outboundRay.OutboundOutput().Close()
@@ -105,7 +95,7 @@ func (h *Handler) Dial(ctx context.Context, dest v2net.Destination) (internet.Co
 			tag := h.senderSettings.ProxySettings.Tag
 			handler := h.outboundManager.GetHandler(tag)
 			if handler != nil {
-				log.Info("Proxyman|OutboundHandler: Proxying to ", tag)
+				log.Trace(errors.New("proxying to ", tag).AtDebug().Path("App", "Proxyman", "OutboundHandler"))
 				ctx = proxy.ContextWithTarget(ctx, dest)
 				stream := ray.NewRay(ctx)
 				go handler.Dispatch(ctx, stream)

+ 65 - 38
common/errors/errors.go

@@ -3,78 +3,112 @@ package errors
 
 import (
 	"fmt"
+	"strings"
 
 	"v2ray.com/core/common/serial"
 )
 
+type Severity int
+
+const (
+	SeverityDebug Severity = iota
+	SeverityInfo
+	SeverityWarning
+	SeverityError
+)
+
 type hasInnerError interface {
 	// Inner returns the underlying error of this one.
 	Inner() error
 }
 
-type actionRequired interface {
-	ActionRequired() bool
+type hasSeverity interface {
+	Severity() Severity
 }
 
 // Error is an error object with underlying error.
 type Error struct {
-	message        string
-	inner          error
-	actionRequired bool
+	message  string
+	inner    error
+	severity Severity
+	path     []string
 }
 
 // Error implements error.Error().
-func (v Error) Error() string {
+func (v *Error) Error() string {
 	msg := v.message
 	if v.inner != nil {
 		msg += " > " + v.inner.Error()
 	}
+	if len(v.path) > 0 {
+		msg = strings.Join(v.path, "|") + ": " + msg
+	}
 	return msg
 }
 
 // Inner implements hasInnerError.Inner()
-func (v Error) Inner() error {
+func (v *Error) Inner() error {
 	if v.inner == nil {
 		return nil
 	}
 	return v.inner
 }
 
-func (v Error) ActionRequired() bool {
-	return v.actionRequired
+func (v *Error) Base(err error) *Error {
+	v.inner = err
+	return v
 }
 
-func (v Error) RequireUserAction() Error {
-	v.actionRequired = true
+func (v *Error) atSeverity(s Severity) *Error {
+	v.severity = s
 	return v
 }
 
-func (v Error) Message(msg ...interface{}) Error {
-	return Error{
-		inner:   v,
-		message: serial.Concat(msg...),
+func (v *Error) Severity() Severity {
+	if v.inner == nil {
+		return v.severity
 	}
+
+	if s, ok := v.inner.(hasSeverity); ok {
+		as := s.Severity()
+		if as > v.severity {
+			return as
+		}
+	}
+
+	return v.severity
 }
 
-func (v Error) Format(format string, values ...interface{}) Error {
-	return v.Message(fmt.Sprintf(format, values...))
+func (v *Error) AtDebug() *Error {
+	return v.atSeverity(SeverityDebug)
 }
 
-// New returns a new error object with message formed from given arguments.
-func New(msg ...interface{}) Error {
-	return Error{
-		message: serial.Concat(msg...),
-	}
+func (v *Error) AtInfo() *Error {
+	return v.atSeverity(SeverityInfo)
+}
+
+func (v *Error) AtWarning() *Error {
+	return v.atSeverity(SeverityWarning)
+}
+
+func (v *Error) AtError() *Error {
+	return v.atSeverity(SeverityError)
 }
 
-// Base returns an Error based on the given error.
-func Base(err error) Error {
-	return Error{
-		inner: err,
+func (v *Error) Path(path ...string) *Error {
+	v.path = path
+	return v
+}
+
+// New returns a new error object with message formed from given arguments.
+func New(msg ...interface{}) *Error {
+	return &Error{
+		message:  serial.Concat(msg...),
+		severity: SeverityInfo,
 	}
 }
 
-func Format(format string, values ...interface{}) error {
+func Format(format string, values ...interface{}) *Error {
 	return New(fmt.Sprintf(format, values...))
 }
 
@@ -93,16 +127,9 @@ func Cause(err error) error {
 	return err
 }
 
-func IsActionRequired(err error) bool {
-	for err != nil {
-		if ar, ok := err.(actionRequired); ok && ar.ActionRequired() {
-			return true
-		}
-		inner, ok := err.(hasInnerError)
-		if !ok || inner.Inner() == nil {
-			break
-		}
-		err = inner.Inner()
+func GetSeverity(err error) Severity {
+	if s, ok := err.(hasSeverity); ok {
+		return s.Severity()
 	}
-	return false
+	return SeverityInfo
 }

+ 8 - 8
common/errors/errors_test.go

@@ -12,16 +12,16 @@ func TestActionRequired(t *testing.T) {
 	assert := assert.On(t)
 
 	err := New("TestError")
-	assert.Bool(IsActionRequired(err)).IsFalse()
+	assert.Bool(GetSeverity(err) == SeverityInfo).IsTrue()
 
-	err = Base(io.EOF).Message("TestError2")
-	assert.Bool(IsActionRequired(err)).IsFalse()
+	err = New("TestError2").Base(io.EOF)
+	assert.Bool(GetSeverity(err) == SeverityInfo).IsTrue()
 
-	err = Base(io.EOF).RequireUserAction().Message("TestError3")
-	assert.Bool(IsActionRequired(err)).IsTrue()
+	err = New("TestError3").Base(io.EOF).AtWarning()
+	assert.Bool(GetSeverity(err) == SeverityWarning).IsTrue()
 
-	err = Base(io.EOF).RequireUserAction().Message("TestError4")
-	err = Base(err).Message("TestError5")
-	assert.Bool(IsActionRequired(err)).IsTrue()
+	err = New("TestError4").Base(io.EOF).AtWarning()
+	err = New("TestError5").Base(err)
+	assert.Bool(GetSeverity(err) == SeverityWarning).IsTrue()
 	assert.String(err.Error()).Contains("EOF")
 }

+ 1 - 1
common/retry/retry.go

@@ -38,7 +38,7 @@ func (r *retryer) On(method func() error) error {
 		<-time.After(time.Duration(delay) * time.Millisecond)
 		attempt++
 	}
-	return errors.Base(ErrRetryFailed).Message(accumulatedError)
+	return errors.New(accumulatedError).Base(ErrRetryFailed)
 }
 
 // Timed returns a retry strategy with fixed interval.

+ 6 - 6
main/main.go

@@ -45,7 +45,7 @@ func GetConfigFormat() core.ConfigFormat {
 
 func startV2Ray() (core.Server, error) {
 	if len(configFile) == 0 {
-		return nil, errors.New("V2Ray: Config file is not set.")
+		return nil, errors.New("config file is not set").Path("Core")
 	}
 	var configInput io.Reader
 	if configFile == "stdin:" {
@@ -54,19 +54,19 @@ func startV2Ray() (core.Server, error) {
 		fixedFile := os.ExpandEnv(configFile)
 		file, err := os.Open(fixedFile)
 		if err != nil {
-			return nil, errors.Base(err).Message("V2Ray: Config file not readable.")
+			return nil, errors.New("config file not readable").Path("Core").Base(err)
 		}
 		defer file.Close()
 		configInput = file
 	}
 	config, err := core.LoadConfig(GetConfigFormat(), configInput)
 	if err != nil {
-		return nil, errors.Base(err).Message("V2Ray: Failed to read config file: ", configFile)
+		return nil, errors.New("failed to read config file: ", configFile).Base(err).Path("Core")
 	}
 
 	server, err := core.New(config)
 	if err != nil {
-		return nil, errors.Base(err).Message("V2Ray: Failed to create initialize.")
+		return nil, errors.New("failed to create initialize").Base(err).Path("Core")
 	}
 
 	return server, nil
@@ -88,12 +88,12 @@ func main() {
 	}
 
 	if *test {
-		fmt.Println("V2Ray: Configuration OK.")
+		fmt.Println("Configuration OK.")
 		return
 	}
 
 	if err := server.Start(); err != nil {
-		fmt.Println("V2Ray: Failed to start. ", err)
+		fmt.Println("Failed to start", err)
 	}
 
 	osSignals := make(chan os.Signal, 1)

+ 2 - 2
proxy/freedom/freedom.go

@@ -102,7 +102,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 		return nil
 	})
 	if err != nil {
-		return errors.Base(err).Message("Freedom: Failed to open connection to ", destination)
+		return errors.New("failed to open connection to ", destination).Base(err).Path("Freedom")
 	}
 	defer conn.Close()
 
@@ -136,7 +136,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
 		input.CloseError()
 		output.CloseError()
-		return errors.Base(err).Message("Freedom: Connection ends.")
+		return errors.New("connection ends").Base(err).Path("Freedom")
 	}
 
 	runtime.KeepAlive(timer)

+ 4 - 4
proxy/http/server.go

@@ -94,7 +94,7 @@ func (s *Server) Process(ctx context.Context, network v2net.Network, conn intern
 	}
 	dest, err := parseHost(host, defaultPort)
 	if err != nil {
-		return errors.Base(err).Message("HTTP: Malformed proxy host: ", host).RequireUserAction()
+		return errors.New("malformed proxy host: ", host).AtWarning().Base(err).Path("HTTP")
 	}
 	log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "")
 
@@ -118,7 +118,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade
 		Close:         false,
 	}
 	if err := response.Write(writer); err != nil {
-		return errors.Base(err).Message("HTTP|Server: Failed to write back OK response.")
+		return errors.New("failed to write back OK response").Base(err).Path("HTTP", "Server")
 	}
 
 	timeout := time.Second * time.Duration(s.config.Timeout)
@@ -152,7 +152,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade
 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
 		ray.InboundInput().CloseError()
 		ray.InboundOutput().CloseError()
-		return errors.Base(err).Message("HTTP|Server: Connection ends.")
+		return errors.New("connection ends").Base(err).Path("HTTP", "Server")
 	}
 
 	runtime.KeepAlive(timer)
@@ -251,7 +251,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, rea
 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
 		input.CloseError()
 		output.CloseError()
-		return errors.Base(err).Message("HTTP|Server: Connection ends.")
+		return errors.New("connection ends").Base(err).Path("HTTP", "Server")
 	}
 
 	return nil

+ 7 - 7
proxy/shadowsocks/client.go

@@ -60,7 +60,7 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale
 		return nil
 	})
 	if err != nil {
-		return errors.Base(err).RequireUserAction().Message("Shadowsocks|Client: Failed to find an available destination.")
+		return errors.New("failed to find an available destination").AtWarning().Base(err).Path("Shadowsocks", "Client")
 	}
 	log.Info("Shadowsocks|Client: Tunneling request to ", destination, " via ", server.Destination())
 
@@ -81,7 +81,7 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale
 	user := server.PickUser()
 	rawAccount, err := user.GetTypedAccount()
 	if err != nil {
-		return errors.Base(err).Message("Shadowsocks|Client: Failed to get a valid user account.").RequireUserAction()
+		return errors.New("failed to get a valid user account").AtWarning().Base(err).Path("Shadowsocks", "Client")
 	}
 	account := rawAccount.(*ShadowsocksAccount)
 	request.User = user
@@ -96,7 +96,7 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale
 		bufferedWriter := buf.NewBufferedWriter(conn)
 		bodyWriter, err := WriteTCPRequest(request, bufferedWriter)
 		if err != nil {
-			return errors.Base(err).Message("Shadowsocks|Client: Failed to write request")
+			return errors.New("failed to write request").Base(err).Path("Shadowsocks", "Client")
 		}
 
 		if err := bufferedWriter.SetBuffered(false); err != nil {
@@ -127,7 +127,7 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale
 		})
 
 		if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
-			return errors.Base(err).Message("Shadowsocks|Client: Connection ends.")
+			return errors.New("connection ends").Base(err).Path("Shadowsocks", "Client")
 		}
 
 		return nil
@@ -142,7 +142,7 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale
 
 		requestDone := signal.ExecuteAsync(func() error {
 			if err := buf.PipeUntilEOF(timer, outboundRay.OutboundInput(), writer); err != nil {
-				return errors.Base(err).Message("Shadowsocks|Client: Failed to transport all UDP request")
+				return errors.New("failed to transport all UDP request").Base(err).Path("Shadowsocks", "Client")
 			}
 			return nil
 		})
@@ -156,13 +156,13 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale
 			}
 
 			if err := buf.PipeUntilEOF(timer, reader, outboundRay.OutboundOutput()); err != nil {
-				return errors.Base(err).Message("Shadowsocks|Client: Failed to transport all UDP response.")
+				return errors.New("failed to transport all UDP response").Base(err).Path("Shadowsocks", "Client")
 			}
 			return nil
 		})
 
 		if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
-			return errors.Base(err).Message("Shadowsocks|Client: Connection ends.")
+			return errors.New("connection ends").Base(err).Path("Shadowsocks", "Client")
 		}
 
 		return nil

+ 1 - 1
proxy/shadowsocks/config.go

@@ -41,7 +41,7 @@ func (v *Account) GetCipher() (Cipher, error) {
 func (v *Account) AsAccount() (protocol.Account, error) {
 	cipher, err := v.GetCipher()
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|Account: Failed to get cipher.")
+		return nil, errors.New("failed to get cipher").Base(err).Path("Shadowsocks", "Account")
 	}
 	return &ShadowsocksAccount{
 		Cipher:      cipher,

+ 28 - 28
proxy/shadowsocks/protocol.go

@@ -25,7 +25,7 @@ const (
 func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
 	rawAccount, err := user.GetTypedAccount()
 	if err != nil {
-		return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.")
+		return nil, nil, errors.New("failed to parse account").Path("Shadowsocks", "TCP").Base(err)
 	}
 	account := rawAccount.(*ShadowsocksAccount)
 
@@ -35,14 +35,14 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea
 	ivLen := account.Cipher.IVSize()
 	err = buffer.AppendSupplier(buf.ReadFullFrom(reader, ivLen))
 	if err != nil {
-		return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IV.")
+		return nil, nil, errors.New("failed to read IV").Path("Shadowsocks", "TCP").Base(err)
 	}
 
 	iv := append([]byte(nil), buffer.BytesTo(ivLen)...)
 
 	stream, err := account.Cipher.NewDecodingStream(account.Key, iv)
 	if err != nil {
-		return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to initialize decoding stream.")
+		return nil, nil, errors.New("failed to initialize decoding stream").Path("Shadowsocks", "TCP").Base(err)
 	}
 	reader = crypto.NewCryptionReader(stream, reader)
 
@@ -56,7 +56,7 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea
 	buffer.Clear()
 	err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 1))
 	if err != nil {
-		return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read address type.")
+		return nil, nil, errors.New("failed to read address type").Path("Shadowsocks", "TCP").Base(err)
 	}
 
 	addrType := (buffer.Byte(0) & 0x0F)
@@ -65,35 +65,35 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea
 	}
 
 	if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled {
-		return nil, nil, errors.New("Shadowsocks|TCP: Rejecting connection with OTA enabled, while server disables OTA.")
+		return nil, nil, errors.New("rejecting connection with OTA enabled, while server disables OTA").Path("Shadowsocks", "TCP")
 	}
 
 	if !request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Enabled {
-		return nil, nil, errors.New("Shadowsocks|TCP: Rejecting connection with OTA disabled, while server enables OTA.")
+		return nil, nil, errors.New("rejecting connection with OTA disabled, while server enables OTA").Path("Shadowsocks", "TCP")
 	}
 
 	switch addrType {
 	case AddrTypeIPv4:
 		err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 4))
 		if err != nil {
-			return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IPv4 address.")
+			return nil, nil, errors.New("failed to read IPv4 address").Path("Shadowsocks", "TCP").Base(err)
 		}
 		request.Address = v2net.IPAddress(buffer.BytesFrom(-4))
 	case AddrTypeIPv6:
 		err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 16))
 		if err != nil {
-			return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IPv6 address.")
+			return nil, nil, errors.New("failed to read IPv6 address").Path("Shadowsocks", "TCP").Base(err)
 		}
 		request.Address = v2net.IPAddress(buffer.BytesFrom(-16))
 	case AddrTypeDomain:
 		err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 1))
 		if err != nil {
-			return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read domain lenth.")
+			return nil, nil, errors.New("failed to read domain lenth.").Path("Shadowsocks", "TCP").Base(err)
 		}
 		domainLength := int(buffer.BytesFrom(-1)[0])
 		err = buffer.AppendSupplier(buf.ReadFullFrom(reader, domainLength))
 		if err != nil {
-			return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read domain.")
+			return nil, nil, errors.New("failed to read domain").Path("Shadowsocks", "TCP").Base(err)
 		}
 		request.Address = v2net.DomainAddress(string(buffer.BytesFrom(-domainLength)))
 	default:
@@ -102,7 +102,7 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea
 
 	err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 2))
 	if err != nil {
-		return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read port.")
+		return nil, nil, errors.New("failed to read port").Path("Shadowsocks", "TCP").Base(err)
 	}
 	request.Port = v2net.PortFromBytes(buffer.BytesFrom(-2))
 
@@ -112,16 +112,16 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea
 
 		err := buffer.AppendSupplier(buf.ReadFullFrom(reader, AuthSize))
 		if err != nil {
-			return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read OTA.")
+			return nil, nil, errors.New("Failed to read OTA").Path("Shadowsocks", "TCP").Base(err)
 		}
 
 		if !bytes.Equal(actualAuth, buffer.BytesFrom(-AuthSize)) {
-			return nil, nil, errors.New("Shadowsocks|TCP: Invalid OTA")
+			return nil, nil, errors.New("invalid OTA").Path("Shadowsocks", "TCP")
 		}
 	}
 
 	if request.Address == nil {
-		return nil, nil, errors.New("Shadowsocks|TCP: Invalid remote address.")
+		return nil, nil, errors.New("invalid remote address.").Path("Shadowsocks", "TCP")
 	}
 
 	var chunkReader buf.Reader
@@ -138,7 +138,7 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
 	user := request.User
 	rawAccount, err := user.GetTypedAccount()
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.")
+		return nil, errors.New("failed to parse account").Path("Shadowsocks", "TCP").Base(err)
 	}
 	account := rawAccount.(*ShadowsocksAccount)
 
@@ -146,12 +146,12 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
 	rand.Read(iv)
 	_, err = writer.Write(iv)
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to write IV.")
+		return nil, errors.New("failed to write IV").Path("Shadowsocks", "TCP")
 	}
 
 	stream, err := account.Cipher.NewEncodingStream(account.Key, iv)
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to create encoding stream.")
+		return nil, errors.New("failed to create encoding stream").Path("Shadowsocks", "TCP").Base(err)
 	}
 
 	writer = crypto.NewCryptionWriter(stream, writer)
@@ -183,7 +183,7 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
 
 	_, err = writer.Write(header.Bytes())
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to write header.")
+		return nil, errors.New("Shadowsocks|TCP: Failed to write header.").Base(err)
 	}
 
 	var chunkWriter buf.Writer
@@ -199,19 +199,19 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
 func ReadTCPResponse(user *protocol.User, reader io.Reader) (buf.Reader, error) {
 	rawAccount, err := user.GetTypedAccount()
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.")
+		return nil, errors.New("Shadowsocks|TCP: Failed to parse account.").Base(err)
 	}
 	account := rawAccount.(*ShadowsocksAccount)
 
 	iv := make([]byte, account.Cipher.IVSize())
 	_, err = io.ReadFull(reader, iv)
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IV.")
+		return nil, errors.New("Shadowsocks|TCP: Failed to read IV.").Base(err)
 	}
 
 	stream, err := account.Cipher.NewDecodingStream(account.Key, iv)
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to initialize decoding stream.")
+		return nil, errors.New("Shadowsocks|TCP: Failed to initialize decoding stream.").Base(err)
 	}
 	return buf.NewReader(crypto.NewCryptionReader(stream, reader)), nil
 }
@@ -220,7 +220,7 @@ func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Wr
 	user := request.User
 	rawAccount, err := user.GetTypedAccount()
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.")
+		return nil, errors.New("Shadowsocks|TCP: Failed to parse account.").Base(err)
 	}
 	account := rawAccount.(*ShadowsocksAccount)
 
@@ -228,12 +228,12 @@ func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Wr
 	rand.Read(iv)
 	_, err = writer.Write(iv)
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to write IV.")
+		return nil, errors.New("Shadowsocks|TCP: Failed to write IV.").Base(err)
 	}
 
 	stream, err := account.Cipher.NewEncodingStream(account.Key, iv)
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to create encoding stream.")
+		return nil, errors.New("Shadowsocks|TCP: Failed to create encoding stream.").Base(err)
 	}
 
 	return buf.NewWriter(crypto.NewCryptionWriter(stream, writer)), nil
@@ -243,7 +243,7 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload *buf.Buffer) (*buf
 	user := request.User
 	rawAccount, err := user.GetTypedAccount()
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|UDP: Failed to parse account.")
+		return nil, errors.New("Shadowsocks|UDP: Failed to parse account.").Base(err)
 	}
 	account := rawAccount.(*ShadowsocksAccount)
 
@@ -278,7 +278,7 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload *buf.Buffer) (*buf
 
 	stream, err := account.Cipher.NewEncodingStream(account.Key, iv)
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to create encoding stream.")
+		return nil, errors.New("Shadowsocks|TCP: Failed to create encoding stream.").Base(err)
 	}
 
 	stream.XORKeyStream(buffer.BytesFrom(ivLen), buffer.BytesFrom(ivLen))
@@ -288,7 +288,7 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload *buf.Buffer) (*buf
 func DecodeUDPPacket(user *protocol.User, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
 	rawAccount, err := user.GetTypedAccount()
 	if err != nil {
-		return nil, nil, errors.Base(err).Message("Shadowsocks|UDP: Failed to parse account.")
+		return nil, nil, errors.New("Shadowsocks|UDP: Failed to parse account.").Base(err)
 	}
 	account := rawAccount.(*ShadowsocksAccount)
 
@@ -298,7 +298,7 @@ func DecodeUDPPacket(user *protocol.User, payload *buf.Buffer) (*protocol.Reques
 
 	stream, err := account.Cipher.NewDecodingStream(account.Key, iv)
 	if err != nil {
-		return nil, nil, errors.Base(err).Message("Shadowsocks|UDP: Failed to initialize decoding stream.")
+		return nil, nil, errors.New("Shadowsocks|UDP: Failed to initialize decoding stream.").Base(err)
 	}
 	stream.XORKeyStream(payload.Bytes(), payload.Bytes())
 

+ 15 - 15
proxy/shadowsocks/server.go

@@ -28,15 +28,15 @@ type Server struct {
 func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
 	space := app.SpaceFromContext(ctx)
 	if space == nil {
-		return nil, errors.New("Shadowsocks|Server: No space in context.")
+		return nil, errors.New("no space in context").Path("Shadowsocks", "Server")
 	}
 	if config.GetUser() == nil {
-		return nil, errors.New("Shadowsocks|Server: User is not specified.")
+		return nil, errors.New("user is not specified").Path("Shadowsocks", "Server")
 	}
 
 	rawAccount, err := config.User.GetTypedAccount()
 	if err != nil {
-		return nil, errors.Base(err).Message("Shadowsocks|Server: Failed to get user account.")
+		return nil, errors.New("failed to get user account").Base(err).Path("Shadowsocks", "Server")
 	}
 	account := rawAccount.(*ShadowsocksAccount)
 
@@ -68,7 +68,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
 	case net.Network_UDP:
 		return s.handlerUDPPayload(ctx, conn, dispatcher)
 	default:
-		return errors.New("Shadowsocks|Server: Unknown network: ", network)
+		return errors.New("unknown network: ", network).Path("Shadowsocks", "Server")
 	}
 }
 
@@ -85,7 +85,7 @@ func (v *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
 		request, data, err := DecodeUDPPacket(v.user, payload)
 		if err != nil {
 			if source, ok := proxy.SourceFromContext(ctx); ok {
-				log.Info("Shadowsocks|Server: Skipping invalid UDP packet from: ", source, ": ", err)
+				log.Trace(errors.New("dropping invalid UDP packet from: ", source).Base(err).Path("Shadowsocks", "Server"))
 				log.Access(source, "", log.AccessRejected, err)
 			}
 			payload.Release()
@@ -93,13 +93,13 @@ func (v *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
 		}
 
 		if request.Option.Has(RequestOptionOneTimeAuth) && v.account.OneTimeAuth == Account_Disabled {
-			log.Info("Shadowsocks|Server: Client payload enables OTA but server doesn't allow it.")
+			log.Trace(errors.New("client payload enables OTA but server doesn't allow it").Path("Shadowsocks", "Server"))
 			payload.Release()
 			continue
 		}
 
 		if !request.Option.Has(RequestOptionOneTimeAuth) && v.account.OneTimeAuth == Account_Enabled {
-			log.Info("Shadowsocks|Server: Client payload disables OTA but server forces it.")
+			log.Trace(errors.New("client payload disables OTA but server forces it").Path("Shadowsocks", "Server"))
 			payload.Release()
 			continue
 		}
@@ -108,7 +108,7 @@ func (v *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
 		if source, ok := proxy.SourceFromContext(ctx); ok {
 			log.Access(source, dest, log.AccessAccepted, "")
 		}
-		log.Info("Shadowsocks|Server: Tunnelling request to ", dest)
+		log.Trace(errors.New("tunnelling request to ", dest).Path("Shadowsocks", "Server"))
 
 		ctx = protocol.ContextWithUser(ctx, request.User)
 		udpServer.Dispatch(ctx, dest, data, func(payload *buf.Buffer) {
@@ -116,7 +116,7 @@ func (v *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
 
 			data, err := EncodeUDPPacket(request, payload)
 			if err != nil {
-				log.Warning("Shadowsocks|Server: Failed to encode UDP packet: ", err)
+				log.Trace(errors.New("failed to encode UDP packet").Base(err).Path("Shadowsocks", "Server").AtWarning())
 				return
 			}
 			defer data.Release()
@@ -134,7 +134,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 	request, bodyReader, err := ReadTCPSession(s.user, bufferedReader)
 	if err != nil {
 		log.Access(conn.RemoteAddr(), "", log.AccessRejected, err)
-		return errors.Base(err).Message("Shadowsocks|Server: Failed to create request from: ", conn.RemoteAddr())
+		return errors.New("failed to create request from: ", conn.RemoteAddr()).Base(err).Path("Shadowsocks", "Server")
 	}
 	conn.SetReadDeadline(time.Time{})
 
@@ -142,7 +142,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 
 	dest := request.Destination()
 	log.Access(conn.RemoteAddr(), dest, log.AccessAccepted, "")
-	log.Info("Shadowsocks|Server: Tunnelling request to ", dest)
+	log.Trace(errors.New("tunnelling request to ", dest).Path("Shadowsocks", "Server"))
 
 	ctx = protocol.ContextWithUser(ctx, request.User)
 
@@ -157,7 +157,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 		bufferedWriter := buf.NewBufferedWriter(conn)
 		responseWriter, err := WriteTCPResponse(request, bufferedWriter)
 		if err != nil {
-			return errors.Base(err).Message("Shadowsocks|Server: Failed to write response.")
+			return errors.New("failed to write response").Base(err).Path("Shadowsocks", "Server")
 		}
 
 		payload, err := ray.InboundOutput().Read()
@@ -174,7 +174,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 		}
 
 		if err := buf.PipeUntilEOF(timer, ray.InboundOutput(), responseWriter); err != nil {
-			return errors.Base(err).Message("Shadowsocks|Server: Failed to transport all TCP response.")
+			return errors.New("failed to transport all TCP response").Base(err).Path("Shadowsocks", "Server")
 		}
 
 		return nil
@@ -184,7 +184,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 		defer ray.InboundInput().Close()
 
 		if err := buf.PipeUntilEOF(timer, bodyReader, ray.InboundInput()); err != nil {
-			return errors.Base(err).Message("Shadowsocks|Server: Failed to transport all TCP request.")
+			return errors.New("failed to transport all TCP request").Base(err).Path("Shadowsocks", "Server")
 		}
 		return nil
 	})
@@ -192,7 +192,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
 		ray.InboundInput().CloseError()
 		ray.InboundOutput().CloseError()
-		return errors.Base(err).Message("Shadowsocks|Server: Connection ends.")
+		return errors.New("connection ends").Base(err).Path("Shadowsocks", "Server")
 	}
 
 	runtime.KeepAlive(timer)

+ 4 - 4
proxy/socks/client.go

@@ -55,7 +55,7 @@ func (c *Client) Process(ctx context.Context, ray ray.OutboundRay, dialer proxy.
 	})
 
 	if err != nil {
-		return errors.Base(err).Message("Socks|Client: Failed to find an available destination.")
+		return errors.New("failed to find an available destination").Base(err).Path("Socks", "Client")
 	}
 
 	defer conn.Close()
@@ -78,7 +78,7 @@ func (c *Client) Process(ctx context.Context, ray ray.OutboundRay, dialer proxy.
 
 	udpRequest, err := ClientHandshake(request, conn, conn)
 	if err != nil {
-		return errors.Base(err).RequireUserAction().Message("Socks|Client: Failed to establish connection to server.")
+		return errors.New("failed to establish connection to server").AtWarning().Base(err).Path("Socks", "Client")
 	}
 
 	ctx, timer := signal.CancelAfterInactivity(ctx, time.Minute*2)
@@ -96,7 +96,7 @@ func (c *Client) Process(ctx context.Context, ray ray.OutboundRay, dialer proxy.
 	} else if request.Command == protocol.RequestCommandUDP {
 		udpConn, err := dialer.Dial(ctx, udpRequest.Destination())
 		if err != nil {
-			return errors.Base(err).Message("Socks|Client: Failed to create UDP connection.")
+			return errors.New("failed to create UDP connection").Base(err).Path("Socks", "Client")
 		}
 		defer udpConn.Close()
 		requestFunc = func() error {
@@ -112,7 +112,7 @@ func (c *Client) Process(ctx context.Context, ray ray.OutboundRay, dialer proxy.
 	requestDone := signal.ExecuteAsync(requestFunc)
 	responseDone := signal.ExecuteAsync(responseFunc)
 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
-		return errors.Base(err).Message("Socks|Client: Connection ends.")
+		return errors.New("connection ends").Base(err).Path("Socks", "Client")
 	}
 
 	runtime.KeepAlive(timer)

+ 16 - 16
proxy/socks/protocol.go

@@ -44,13 +44,13 @@ func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol
 	request := new(protocol.RequestHeader)
 
 	if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil {
-		return nil, errors.Base(err).Message("Socks|Server: Insufficient header.")
+		return nil, errors.New("insufficient header").Base(err).Path("Socks", "Server")
 	}
 
 	version := buffer.Byte(0)
 	if version == socks4Version {
 		if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 6)); err != nil {
-			return nil, errors.Base(err).Message("Socks|Server: Insufficient header.")
+			return nil, errors.New("insufficient header").Base(err).Path("Socks", "Server")
 		}
 		port := v2net.PortFromBytes(buffer.BytesRange(2, 4))
 		address := v2net.IPAddress(buffer.BytesRange(4, 8))
@@ -61,7 +61,7 @@ func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol
 		if address.IP()[0] == 0x00 {
 			domain, err := readUntilNull(reader)
 			if err != nil {
-				return nil, errors.Base(err).Message("Socks|Server: Failed to read domain for socks 4a.")
+				return nil, errors.New("failed to read domain for socks 4a").Base(err).Path("Socks", "Server")
 			}
 			address = v2net.DomainAddress(domain)
 		}
@@ -85,7 +85,7 @@ func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol
 	if version == socks5Version {
 		nMethod := int(buffer.Byte(1))
 		if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, nMethod)); err != nil {
-			return nil, errors.Base(err).Message("Socks|Server: Failed to read auth methods.")
+			return nil, errors.New("failed to read auth methods").Base(err).Path("Socks", "Server")
 		}
 
 		var expectedAuth byte = authNotRequired
@@ -95,37 +95,37 @@ func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol
 
 		if !hasAuthMethod(expectedAuth, buffer.BytesRange(2, 2+nMethod)) {
 			writeSocks5AuthenticationResponse(writer, socks5Version, authNoMatchingMethod)
-			return nil, errors.New("Socks|Server: No matching auth method.")
+			return nil, errors.New("no matching auth method").Path("Socks", "Server")
 		}
 
 		if err := writeSocks5AuthenticationResponse(writer, socks5Version, expectedAuth); err != nil {
-			return nil, errors.Base(err).Message("Socks|Server: Failed to write auth response.")
+			return nil, errors.New("failed to write auth response").Base(err).Path("Socks", "Server")
 		}
 
 		if expectedAuth == authPassword {
 			username, password, err := readUsernamePassword(reader)
 			if err != nil {
-				return nil, errors.Base(err).Message("Socks|Server: Failed to read username and password for authentication.")
+				return nil, errors.New("failed to read username and password for authentication").Base(err).Path("Socks", "Server")
 			}
 
 			if !s.config.HasAccount(username, password) {
 				writeSocks5AuthenticationResponse(writer, 0x01, 0xFF)
-				return nil, errors.New("Socks|Server: Invalid username or password.")
+				return nil, errors.New("invalid username or password").Path("Socks", "Server")
 			}
 
 			if err := writeSocks5AuthenticationResponse(writer, 0x01, 0x00); err != nil {
-				return nil, errors.Base(err).Message("Socks|Server: Failed to write auth response.")
+				return nil, errors.New("failed to write auth response").Base(err).Path("Socks", "Server")
 			}
 		}
 		buffer.Clear()
 		if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 4)); err != nil {
-			return nil, errors.Base(err).Message("Socks|Server: Failed to read request.")
+			return nil, errors.New("failed to read request").Base(err).Path("Socks", "Server")
 		}
 
 		cmd := buffer.Byte(1)
 		if cmd == cmdTCPBind || (cmd == cmdUDPPort && !s.config.UdpEnabled) {
 			writeSocks5Response(writer, statusCmdNotSupport, v2net.AnyIP, v2net.Port(0))
-			return nil, errors.New("Socks|Server: Unsupported command: ", cmd)
+			return nil, errors.New("unsupported command: ", cmd).Path("Socks", "Server")
 		}
 
 		switch cmd {
@@ -161,7 +161,7 @@ func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol
 			}
 			request.Address = v2net.ParseAddress(string(buffer.BytesFrom(-domainLength)))
 		default:
-			return nil, errors.New("Socks|Server: Unknown address type: ", addrType)
+			return nil, errors.New("Unknown address type: ", addrType).Path("Socks", "Server")
 		}
 
 		if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil {
@@ -186,7 +186,7 @@ func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol
 		return request, nil
 	}
 
-	return nil, errors.New("Socks|Server: Unknown Socks version: ", version)
+	return nil, errors.New("unknown Socks version: ", version).Path("Socks", "Server")
 }
 
 func readUsernamePassword(reader io.Reader) (string, string, error) {
@@ -230,7 +230,7 @@ func readUntilNull(reader io.Reader) (string, error) {
 		}
 		size++
 		if size == 256 {
-			return "", errors.New("Socks|Server: Buffer overrun.")
+			return "", errors.New("buffer overrun").Path("Socks", "Server")
 		}
 	}
 }
@@ -400,10 +400,10 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
 	}
 
 	if b.Byte(0) != socks5Version {
-		return nil, errors.New("Socks|Client: Unexpected server version: ", b.Byte(0)).RequireUserAction()
+		return nil, errors.New("Socks|Client: Unexpected server version: ", b.Byte(0)).AtWarning()
 	}
 	if b.Byte(1) != authByte {
-		return nil, errors.New("Socks|Client: auth method not supported.").RequireUserAction()
+		return nil, errors.New("Socks|Client: auth method not supported.").AtWarning()
 	}
 
 	if authByte == authPassword {

+ 5 - 5
proxy/socks/server.go

@@ -29,7 +29,7 @@ type Server struct {
 func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
 	space := app.SpaceFromContext(ctx)
 	if space == nil {
-		return nil, errors.New("Socks|Server: No space in context.").RequireUserAction()
+		return nil, errors.New("Socks|Server: No space in context.").AtWarning()
 	}
 	s := &Server{
 		config: config,
@@ -129,7 +129,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ
 
 		v2reader := buf.NewReader(reader)
 		if err := buf.PipeUntilEOF(timer, v2reader, input); err != nil {
-			return errors.Base(err).Message("Socks|Server: Failed to transport all TCP request.")
+			return errors.New("failed to transport all TCP request").Base(err).Path("Socks", "Server")
 		}
 		return nil
 	})
@@ -137,7 +137,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ
 	responseDone := signal.ExecuteAsync(func() error {
 		v2writer := buf.NewWriter(writer)
 		if err := buf.PipeUntilEOF(timer, output, v2writer); err != nil {
-			return errors.Base(err).Message("Socks|Server: Failed to transport all TCP response.")
+			return errors.New("failed to transport all TCP response").Base(err).Path("Socks", "Server")
 		}
 		return nil
 	})
@@ -145,7 +145,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ
 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
 		input.CloseError()
 		output.CloseError()
-		return errors.Base(err).Message("Socks|Server: Connection ends.")
+		return errors.New("connection ends").Base(err).Path("Socks", "Server")
 	}
 
 	runtime.KeepAlive(timer)
@@ -157,7 +157,7 @@ func (v *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
 	udpServer := udp.NewDispatcher(dispatcher)
 
 	if source, ok := proxy.SourceFromContext(ctx); ok {
-		log.Info("Socks|Server: Client UDP connection from ", source)
+		log.Trace(errors.New("client UDP connection from ", source).Path("Socks", "Server"))
 	}
 
 	reader := buf.NewReader(conn)

+ 12 - 12
proxy/vmess/encoding/server.go

@@ -123,7 +123,7 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 
 	_, err := io.ReadFull(reader, buffer[:protocol.IDBytesLen])
 	if err != nil {
-		return nil, errors.Base(err).Message("VMess|Server: Failed to read request header.")
+		return nil, errors.New("failed to read request header").Base(err).Path("VMess", "Server")
 	}
 
 	user, timestamp, valid := v.userValidator.Get(buffer[:protocol.IDBytesLen])
@@ -136,7 +136,7 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 	iv := timestampHash.Sum(nil)
 	account, err := user.GetTypedAccount()
 	if err != nil {
-		return nil, errors.Base(err).Message("VMess|Server: Failed to get user account.")
+		return nil, errors.New("failed to get user account").Base(err).Path("VMess", "Server")
 	}
 	vmessAccount := account.(*vmess.InternalAccount)
 
@@ -145,7 +145,7 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 
 	nBytes, err := io.ReadFull(decryptor, buffer[:41])
 	if err != nil {
-		return nil, errors.Base(err).Message("VMess|Server: Failed to read request header.")
+		return nil, errors.New("failed to read request header").Base(err).Path("VMess", "Server")
 	}
 	bufferLen := nBytes
 
@@ -155,7 +155,7 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 	}
 
 	if request.Version != Version {
-		return nil, errors.New("VMess|Server: Invalid protocol version ", request.Version)
+		return nil, errors.New("invalid protocol version ", request.Version).Path("VMess", "Server")
 	}
 
 	v.requestBodyIV = append([]byte(nil), buffer[1:17]...)   // 16 bytes
@@ -165,7 +165,7 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 	copy(sid.key[:], v.requestBodyKey)
 	copy(sid.nonce[:], v.requestBodyIV)
 	if v.sessionHistory.has(sid) {
-		return nil, errors.New("VMess|Server: Duplicated session id. Possibly under replay attack.")
+		return nil, errors.New("duplicated session id, possibly under replay attack").Path("VMess", "Server")
 	}
 	v.sessionHistory.add(sid)
 
@@ -183,28 +183,28 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 		_, err = io.ReadFull(decryptor, buffer[41:45]) // 4 bytes
 		bufferLen += 4
 		if err != nil {
-			return nil, errors.Base(err).Message("VMess|Server: Failed to read IPv4.")
+			return nil, errors.New("failed to read IPv4 address").Base(err).Path("VMess", "Server")
 		}
 		request.Address = net.IPAddress(buffer[41:45])
 	case AddrTypeIPv6:
 		_, err = io.ReadFull(decryptor, buffer[41:57]) // 16 bytes
 		bufferLen += 16
 		if err != nil {
-			return nil, errors.Base(err).Message("VMess|Server: Failed to read IPv6 address.")
+			return nil, errors.New("failed to read IPv6 address").Base(err).Path("VMess", "Server")
 		}
 		request.Address = net.IPAddress(buffer[41:57])
 	case AddrTypeDomain:
 		_, err = io.ReadFull(decryptor, buffer[41:42])
 		if err != nil {
-			return nil, errors.Base(err).Message("VMess:Server: Failed to read domain.")
+			return nil, errors.New("failed to read domain address").Base(err).Path("VMess", "Server")
 		}
 		domainLength := int(buffer[41])
 		if domainLength == 0 {
-			return nil, errors.New("VMess|Server: Zero length domain.")
+			return nil, errors.New("zero length domain").Base(err).Path("VMess", "Server")
 		}
 		_, err = io.ReadFull(decryptor, buffer[42:42+domainLength])
 		if err != nil {
-			return nil, errors.Base(err).Message("VMess|Server: Failed to read domain.")
+			return nil, errors.New("failed to read domain address").Base(err).Path("VMess", "Server")
 		}
 		bufferLen += 1 + domainLength
 		request.Address = net.DomainAddress(string(buffer[42 : 42+domainLength]))
@@ -213,14 +213,14 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 	if padingLen > 0 {
 		_, err = io.ReadFull(decryptor, buffer[bufferLen:bufferLen+padingLen])
 		if err != nil {
-			return nil, errors.Base(err).Message("VMess|Server: Failed to read padding.")
+			return nil, errors.New("failed to read padding").Base(err).Path("VMess", "Server")
 		}
 		bufferLen += padingLen
 	}
 
 	_, err = io.ReadFull(decryptor, buffer[bufferLen:bufferLen+4])
 	if err != nil {
-		return nil, errors.Base(err).Message("VMess|Server: Failed to read checksum.")
+		return nil, errors.New("failed to read checksum").Base(err).Path("VMess", "Server")
 	}
 
 	fnv1a := fnv.New32a()

+ 2 - 2
proxy/vmess/inbound/inbound.go

@@ -226,12 +226,12 @@ func (v *Handler) Process(ctx context.Context, network net.Network, connection i
 		connection.SetReusable(false)
 		input.CloseError()
 		output.CloseError()
-		return errors.Base(err).Message("VMess|Inbound: Error during processing.")
+		return errors.New("error during processing").Base(err).Path("VMess", "Inbound")
 	}
 
 	if err := writer.Flush(); err != nil {
 		connection.SetReusable(false)
-		return errors.Base(err).Message("VMess|Inbound: Error during flushing remaining data.")
+		return errors.New("error during flushing remaining data").Base(err).Path("VMess", "Inbound")
 	}
 
 	runtime.KeepAlive(timer)

+ 5 - 6
proxy/vmess/outbound/outbound.go

@@ -61,7 +61,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 		return nil
 	})
 	if err != nil {
-		return errors.Base(err).RequireUserAction().Message("VMess|Outbound: Failed to find an available destination.")
+		return errors.New("VMess|Outbound: Failed to find an available destination.").Base(err).AtWarning()
 	}
 	defer conn.Close()
 
@@ -86,7 +86,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 
 	rawAccount, err := request.User.GetTypedAccount()
 	if err != nil {
-		return errors.Base(err).RequireUserAction().Message("VMess|Outbound: Failed to get user account.")
+		return errors.New("VMess|Outbound: Failed to get user account.").Base(err).AtWarning()
 	}
 	account := rawAccount.(*vmess.InternalAccount)
 	request.Security = account.Security
@@ -114,11 +114,11 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 		bodyWriter := session.EncodeRequestBody(request, writer)
 		firstPayload, err := input.ReadTimeout(time.Millisecond * 500)
 		if err != nil && err != buf.ErrReadTimeout {
-			return errors.Base(err).Message("VMess|Outbound: Failed to get first payload.")
+			return errors.New("failed to get first payload").Base(err).Path("VMess", "Outbound")
 		}
 		if !firstPayload.IsEmpty() {
 			if err := bodyWriter.Write(firstPayload); err != nil {
-				return errors.Base(err).Message("VMess|Outbound: Failed to write first payload.")
+				return errors.New("failed to write first payload").Base(err).Path("VMess", "Outbound")
 			}
 			firstPayload.Release()
 		}
@@ -166,9 +166,8 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 	})
 
 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil {
-		log.Info("VMess|Outbound: Connection ending with ", err)
 		conn.SetReusable(false)
-		return err
+		return errors.New("connection ends").Base(err).Path("VMess", "Outbound")
 	}
 	runtime.KeepAlive(timer)
 

+ 1 - 1
tools/conf/blackhole.go

@@ -29,7 +29,7 @@ func (v *BlackholeConfig) Build() (*serial.TypedMessage, error) {
 	if v.Response != nil {
 		response, _, err := configLoader.Load(v.Response)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Failed to parse Blackhole response config.")
+			return nil, errors.New("Config: Failed to parse Blackhole response config.").Base(err)
 		}
 		responseSettings, err := response.(Buildable).Build()
 		if err != nil {

+ 2 - 2
tools/conf/freedom.go

@@ -31,11 +31,11 @@ func (v *FreedomConfig) Build() (*serial.TypedMessage, error) {
 	if len(v.Redirect) > 0 {
 		host, portStr, err := net.SplitHostPort(v.Redirect)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid redirect address: ", v.Redirect, ": ", err)
+			return nil, errors.New("Config: Invalid redirect address: ", v.Redirect, ": ", err).Base(err)
 		}
 		port, err := v2net.PortFromString(portStr)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid redirect port: ", v.Redirect, ": ", err)
+			return nil, errors.New("Config: Invalid redirect port: ", v.Redirect, ": ", err).Base(err)
 		}
 		if len(host) == 0 {
 			host = "127.0.0.1"

+ 10 - 10
tools/conf/router.go

@@ -69,7 +69,7 @@ func parseIP(s string) (*router.CIDR, error) {
 		if len(mask) > 0 {
 			bits64, err := strconv.ParseUint(mask, 10, 32)
 			if err != nil {
-				return nil, errors.Base(err).Message("Config: invalid network mask for router: ", mask)
+				return nil, errors.New("Config: invalid network mask for router: ", mask).Base(err)
 			}
 			bits = uint32(bits64)
 		}
@@ -85,7 +85,7 @@ func parseIP(s string) (*router.CIDR, error) {
 		if len(mask) > 0 {
 			bits64, err := strconv.ParseUint(mask, 10, 32)
 			if err != nil {
-				return nil, errors.Base(err).Message("Config: invalid network mask for router: ", mask)
+				return nil, errors.New("Config: invalid network mask for router: ", mask).Base(err)
 			}
 			bits = uint32(bits64)
 		}
@@ -139,7 +139,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
 		for _, ip := range *rawFieldRule.IP {
 			ipRule, err := parseIP(ip)
 			if err != nil {
-				return nil, errors.Base(err).Message("Config: invalid IP: ", ip)
+				return nil, errors.New("Config: invalid IP: ", ip).Base(err)
 			}
 			rule.Cidr = append(rule.Cidr, ipRule)
 		}
@@ -157,7 +157,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
 		for _, ip := range *rawFieldRule.SourceIP {
 			ipRule, err := parseIP(ip)
 			if err != nil {
-				return nil, errors.Base(err).Message("Config: invalid IP: ", ip)
+				return nil, errors.New("Config: invalid IP: ", ip).Base(err)
 			}
 			rule.SourceCidr = append(rule.SourceCidr, ipRule)
 		}
@@ -182,26 +182,26 @@ func ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
 	rawRule := new(RouterRule)
 	err := json.Unmarshal(msg, rawRule)
 	if err != nil {
-		return nil, errors.Base(err).Message("Config: Invalid router rule.")
+		return nil, errors.New("Config: Invalid router rule.").Base(err)
 	}
 	if rawRule.Type == "field" {
 		fieldrule, err := parseFieldRule(msg)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid field rule.")
+			return nil, errors.New("Config: Invalid field rule.").Base(err)
 		}
 		return fieldrule, nil
 	}
 	if rawRule.Type == "chinaip" {
 		chinaiprule, err := parseChinaIPRule(msg)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid chinaip rule.")
+			return nil, errors.New("Config: Invalid chinaip rule.").Base(err)
 		}
 		return chinaiprule, nil
 	}
 	if rawRule.Type == "chinasites" {
 		chinasitesrule, err := parseChinaSitesRule(msg)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid chinasites rule.")
+			return nil, errors.New("Config: Invalid chinasites rule.").Base(err)
 		}
 		return chinasitesrule, nil
 	}
@@ -212,11 +212,11 @@ func parseChinaIPRule(data []byte) (*router.RoutingRule, error) {
 	rawRule := new(RouterRule)
 	err := json.Unmarshal(data, rawRule)
 	if err != nil {
-		return nil, errors.Base(err).Message("Config: Invalid router rule.")
+		return nil, errors.New("Config: Invalid router rule.").Base(err)
 	}
 	var chinaIPs geoip.CountryIPRange
 	if err := proto.Unmarshal(geoip.ChinaIPs, &chinaIPs); err != nil {
-		return nil, errors.Base(err).Message("Config: Invalid china ips.")
+		return nil, errors.New("Config: Invalid china ips.").Base(err)
 	}
 	return &router.RoutingRule{
 		Tag:  rawRule.OutboundTag,

+ 2 - 2
tools/conf/socks.go

@@ -80,11 +80,11 @@ func (v *SocksClientConfig) Build() (*serial.TypedMessage, error) {
 		for _, rawUser := range serverConfig.Users {
 			user := new(protocol.User)
 			if err := json.Unmarshal(rawUser, user); err != nil {
-				return nil, errors.Base(err).Message("Config: Failed to parse Socks user.")
+				return nil, errors.New("Config: Failed to parse Socks user.").Base(err)
 			}
 			account := new(SocksAccount)
 			if err := json.Unmarshal(rawUser, account); err != nil {
-				return nil, errors.Base(err).Message("Config: Failed to parse socks account.")
+				return nil, errors.New("Config: Failed to parse socks account.").Base(err)
 			}
 			user.Account = serial.ToTypedMessage(account.Build())
 			server.User = append(server.User, user)

+ 3 - 3
tools/conf/transport.go

@@ -18,7 +18,7 @@ func (v *TransportConfig) Build() (*transport.Config, error) {
 	if v.TCPConfig != nil {
 		ts, err := v.TCPConfig.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Failed to build TCP config.")
+			return nil, errors.New("Config: Failed to build TCP config.").Base(err)
 		}
 		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
 			Protocol: internet.TransportProtocol_TCP,
@@ -29,7 +29,7 @@ func (v *TransportConfig) Build() (*transport.Config, error) {
 	if v.KCPConfig != nil {
 		ts, err := v.KCPConfig.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Failed to build mKCP config.")
+			return nil, errors.New("Config: Failed to build mKCP config.").Base(err)
 		}
 		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
 			Protocol: internet.TransportProtocol_MKCP,
@@ -40,7 +40,7 @@ func (v *TransportConfig) Build() (*transport.Config, error) {
 	if v.WSConfig != nil {
 		ts, err := v.WSConfig.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Failed to build WebSocket config.")
+			return nil, errors.New("Config: Failed to build WebSocket config.").Base(err)
 		}
 		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
 			Protocol: internet.TransportProtocol_WebSocket,

+ 10 - 10
tools/conf/transport_internet.go

@@ -84,11 +84,11 @@ func (v *KCPConfig) Build() (*serial.TypedMessage, error) {
 	if len(v.HeaderConfig) > 0 {
 		headerConfig, _, err := kcpHeaderLoader.Load(v.HeaderConfig)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid mKCP header config.")
+			return nil, errors.New("Config: Invalid mKCP header config.").Base(err)
 		}
 		ts, err := headerConfig.(Buildable).Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid mKCP header config.")
+			return nil, errors.New("Config: Invalid mKCP header config.").Base(err)
 		}
 		config.HeaderConfig = ts
 	}
@@ -111,11 +111,11 @@ func (v *TCPConfig) Build() (*serial.TypedMessage, error) {
 	if len(v.HeaderConfig) > 0 {
 		headerConfig, _, err := tcpHeaderLoader.Load(v.HeaderConfig)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid TCP header config.")
+			return nil, errors.New("Config: Invalid TCP header config.").Base(err)
 		}
 		ts, err := headerConfig.(Buildable).Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid TCP header config.")
+			return nil, errors.New("Config: Invalid TCP header config.").Base(err)
 		}
 		config.HeaderSettings = ts
 	}
@@ -156,11 +156,11 @@ func (v *TLSConfig) Build() (*serial.TypedMessage, error) {
 	for idx, certConf := range v.Certs {
 		cert, err := ioutil.ReadFile(certConf.CertFile)
 		if err != nil {
-			return nil, errors.Base(err).Message("Failed to load TLS certificate file: ", certConf.CertFile)
+			return nil, errors.New("Failed to load TLS certificate file: ", certConf.CertFile).Base(err)
 		}
 		key, err := ioutil.ReadFile(certConf.KeyFile)
 		if err != nil {
-			return nil, errors.Base(err).Message("Failed to load TLS key file: ", certConf.KeyFile)
+			return nil, errors.New("Failed to load TLS key file: ", certConf.KeyFile).Base(err)
 		}
 		config.Certificate[idx] = &tls.Certificate{
 			Key:         key,
@@ -216,7 +216,7 @@ func (v *StreamConfig) Build() (*internet.StreamConfig, error) {
 		}
 		ts, err := tlsSettings.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Failed to build TLS config.")
+			return nil, errors.New("Failed to build TLS config.").Base(err)
 		}
 		config.SecuritySettings = append(config.SecuritySettings, ts)
 		config.SecurityType = ts.Type
@@ -224,7 +224,7 @@ func (v *StreamConfig) Build() (*internet.StreamConfig, error) {
 	if v.TCPSettings != nil {
 		ts, err := v.TCPSettings.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Failed to build TCP config.")
+			return nil, errors.New("Failed to build TCP config.").Base(err)
 		}
 		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
 			Protocol: internet.TransportProtocol_TCP,
@@ -234,7 +234,7 @@ func (v *StreamConfig) Build() (*internet.StreamConfig, error) {
 	if v.KCPSettings != nil {
 		ts, err := v.KCPSettings.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Failed to build mKCP config.")
+			return nil, errors.New("Failed to build mKCP config.").Base(err)
 		}
 		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
 			Protocol: internet.TransportProtocol_MKCP,
@@ -244,7 +244,7 @@ func (v *StreamConfig) Build() (*internet.StreamConfig, error) {
 	if v.WSSettings != nil {
 		ts, err := v.WSSettings.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Failed to build WebSocket config.")
+			return nil, errors.New("Failed to build WebSocket config.").Base(err)
 		}
 		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
 			Protocol: internet.TransportProtocol_WebSocket,

+ 7 - 7
tools/conf/v2ray.go

@@ -63,7 +63,7 @@ func (v *InboundConnectionConfig) Build() (*proxyman.InboundHandlerConfig, error
 
 	jsonConfig, err := inboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
 	if err != nil {
-		return nil, errors.Base(err).Message("Config: Failed to load inbound config.")
+		return nil, errors.New("Config: Failed to load inbound config.").Base(err)
 	}
 	if dokodemoConfig, ok := jsonConfig.(*DokodemoConfig); ok {
 		receiverConfig.ReceiveOriginalDestination = dokodemoConfig.Redirect
@@ -114,7 +114,7 @@ func (v *OutboundConnectionConfig) Build() (*proxyman.OutboundHandlerConfig, err
 	if v.ProxySettings != nil {
 		ps, err := v.ProxySettings.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid outbound proxy settings.")
+			return nil, errors.New("Config: Invalid outbound proxy settings.").Base(err)
 		}
 		senderSettings.ProxySettings = ps
 	}
@@ -127,7 +127,7 @@ func (v *OutboundConnectionConfig) Build() (*proxyman.OutboundHandlerConfig, err
 
 	rawConfig, err := outboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
 	if err != nil {
-		return nil, errors.Base(err).Message("Config: Failed to parse outbound config.")
+		return nil, errors.New("Config: Failed to parse outbound config.").Base(err)
 	}
 	ts, err := rawConfig.(Buildable).Build()
 	if err != nil {
@@ -215,7 +215,7 @@ func (v *InboundDetourConfig) Build() (*proxyman.InboundHandlerConfig, error) {
 
 	rawConfig, err := inboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
 	if err != nil {
-		return nil, errors.Base(err).Message("Config: Failed to load inbound detour config.")
+		return nil, errors.New("Config: Failed to load inbound detour config.").Base(err)
 	}
 	if dokodemoConfig, ok := rawConfig.(*DokodemoConfig); ok {
 		receiverSettings.ReceiveOriginalDestination = dokodemoConfig.Redirect
@@ -264,7 +264,7 @@ func (v *OutboundDetourConfig) Build() (*proxyman.OutboundHandlerConfig, error)
 	if v.ProxySettings != nil {
 		ps, err := v.ProxySettings.Build()
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid outbound detour proxy settings.")
+			return nil, errors.New("Config: Invalid outbound detour proxy settings.").Base(err)
 		}
 		senderSettings.ProxySettings = ps
 	}
@@ -277,7 +277,7 @@ func (v *OutboundDetourConfig) Build() (*proxyman.OutboundHandlerConfig, error)
 
 	rawConfig, err := outboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
 	if err != nil {
-		return nil, errors.Base(err).Message("Config: Failed to parse to outbound detour config.")
+		return nil, errors.New("Config: Failed to parse to outbound detour config.").Base(err)
 	}
 	ts, err := rawConfig.(Buildable).Build()
 	if err != nil {
@@ -380,7 +380,7 @@ func init() {
 		})
 		err := decoder.Decode(jsonConfig)
 		if err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid V2Ray config.")
+			return nil, errors.New("Config: Invalid V2Ray config.").Base(err)
 		}
 
 		return jsonConfig.Build()

+ 4 - 4
tools/conf/vmess.go

@@ -95,11 +95,11 @@ func (v *VMessInboundConfig) Build() (*serial.TypedMessage, error) {
 	for idx, rawData := range v.Users {
 		user := new(protocol.User)
 		if err := json.Unmarshal(rawData, user); err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid VMess user.")
+			return nil, errors.New("Config: Invalid VMess user.").Base(err)
 		}
 		account := new(VMessAccount)
 		if err := json.Unmarshal(rawData, account); err != nil {
-			return nil, errors.Base(err).Message("Config: Invalid VMess user.")
+			return nil, errors.New("Config: Invalid VMess user.").Base(err)
 		}
 		user.Account = serial.ToTypedMessage(account.Build())
 		config.User[idx] = user
@@ -141,11 +141,11 @@ func (v *VMessOutboundConfig) Build() (*serial.TypedMessage, error) {
 		for _, rawUser := range rec.Users {
 			user := new(protocol.User)
 			if err := json.Unmarshal(rawUser, user); err != nil {
-				return nil, errors.Base(err).Message("Config: Invalid VMess user.")
+				return nil, errors.New("Config: Invalid VMess user.").Base(err)
 			}
 			account := new(VMessAccount)
 			if err := json.Unmarshal(rawUser, account); err != nil {
-				return nil, errors.Base(err).Message("Config: Invalid VMess user.")
+				return nil, errors.New("Config: Invalid VMess user.").Base(err)
 			}
 			user.Account = serial.ToTypedMessage(account.Build())
 			spec.User = append(spec.User, user)

+ 2 - 2
transport/internet/kcp/dialer.go

@@ -135,11 +135,11 @@ func DialKCP(ctx context.Context, dest v2net.Destination) (internet.Connection,
 	clientConn := conn.(*ClientConnection)
 	header, err := kcpSettings.GetPackerHeader()
 	if err != nil {
-		return nil, errors.Base(err).Message("KCP|Dialer: Failed to create packet header.")
+		return nil, errors.New("KCP|Dialer: Failed to create packet header.").Base(err)
 	}
 	security, err := kcpSettings.GetSecurity()
 	if err != nil {
-		return nil, errors.Base(err).Message("KCP|Dialer: Failed to create security.")
+		return nil, errors.New("KCP|Dialer: Failed to create security.").Base(err)
 	}
 	clientConn.ResetSecurity(header, security)
 	conv := uint16(atomic.AddUint32(&globalConv, 1))

+ 2 - 2
transport/internet/kcp/listener.go

@@ -98,11 +98,11 @@ func NewListener(ctx context.Context, address v2net.Address, port v2net.Port, co
 
 	header, err := kcpSettings.GetPackerHeader()
 	if err != nil {
-		return nil, errors.Base(err).Message("KCP|Listener: Failed to create packet header.")
+		return nil, errors.New("KCP|Listener: Failed to create packet header.").Base(err)
 	}
 	security, err := kcpSettings.GetSecurity()
 	if err != nil {
-		return nil, errors.Base(err).Message("KCP|Listener: Failed to create security.")
+		return nil, errors.New("KCP|Listener: Failed to create security.").Base(err)
 	}
 	l := &Listener{
 		header:   header,

+ 2 - 2
transport/internet/tcp/dialer.go

@@ -48,11 +48,11 @@ func Dial(ctx context.Context, dest v2net.Destination) (internet.Connection, err
 		if tcpSettings.HeaderSettings != nil {
 			headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
 			if err != nil {
-				return nil, errors.Base(err).Message("Internet|TCP: Failed to get header settings.")
+				return nil, errors.New("Internet|TCP: Failed to get header settings.").Base(err)
 			}
 			auth, err := internet.CreateConnectionAuthenticator(headerConfig)
 			if err != nil {
-				return nil, errors.Base(err).Message("Internet|TCP: Failed to create header authenticator.")
+				return nil, errors.New("Internet|TCP: Failed to create header authenticator.").Base(err)
 			}
 			conn = auth.Client(conn)
 		}

+ 2 - 2
transport/internet/tcp/hub.go

@@ -56,11 +56,11 @@ func ListenTCP(ctx context.Context, address v2net.Address, port v2net.Port, conn
 	if tcpSettings.HeaderSettings != nil {
 		headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
 		if err != nil {
-			return nil, errors.Base(err).Message("Internet|TCP: Invalid header settings.")
+			return nil, errors.New("Internet|TCP: Invalid header settings.").Base(err)
 		}
 		auth, err := internet.CreateConnectionAuthenticator(headerConfig)
 		if err != nil {
-			return nil, errors.Base(err).Message("Internet|TCP: Invalid header settings.")
+			return nil, errors.New("Internet|TCP: Invalid header settings.").Base(err)
 		}
 		l.authConfig = auth
 	}

+ 1 - 1
transport/internet/tcp_hub.go

@@ -48,7 +48,7 @@ func ListenTCP(ctx context.Context, address v2net.Address, port v2net.Port, conn
 	}
 	listener, err := listenFunc(ctx, address, port, conns)
 	if err != nil {
-		return nil, errors.Base(err).Message("Internet|TCPHub: Failed to listen on address: ", address, ":", port)
+		return nil, errors.New("failed to listen on address: ", address, ":", port).Base(err).Path("Internet", "TCPHub")
 	}
 	return listener, nil
 }

+ 2 - 2
transport/internet/udp/hub.go

@@ -97,11 +97,11 @@ func ListenUDP(address v2net.Address, port v2net.Port, option ListenOption) (*Hu
 	if option.ReceiveOriginalDest {
 		fd, err := internal.GetSysFd(udpConn)
 		if err != nil {
-			return nil, errors.Base(err).Message("UDP|Listener: Failed to get fd.")
+			return nil, errors.New("failed to get fd").Base(err).Path("UDP", "Listener")
 		}
 		err = SetOriginalDestOptions(fd)
 		if err != nil {
-			return nil, errors.Base(err).Message("UDP|Listener: Failed to set socket options.")
+			return nil, errors.New("failed to set socket options").Base(err).Path("UDP", "Listener")
 		}
 	}
 	ctx, cancel := context.WithCancel(context.Background())

+ 2 - 2
transport/internet/websocket/dialer.go

@@ -32,7 +32,7 @@ func Dial(ctx context.Context, dest v2net.Destination) (internet.Connection, err
 		var err error
 		conn, err = dialWebsocket(ctx, dest)
 		if err != nil {
-			return nil, errors.Base(err).Message("WebSocket|Dialer: Dial failed.")
+			return nil, errors.New("dial failed").Path("WebSocket", "Dialer")
 		}
 	}
 	return internal.NewConnection(id, conn, globalCache, internal.ReuseConnection(wsSettings.IsConnectionReuse())), nil
@@ -81,7 +81,7 @@ func dialWebsocket(ctx context.Context, dest v2net.Destination) (net.Conn, error
 		if resp != nil {
 			reason = resp.Status
 		}
-		return nil, errors.Base(err).Message("WebSocket|Dialer: Failed to dial to (", uri, "): ", reason)
+		return nil, errors.New("failed to dial to (", uri, "): ", reason).Base(err).Path("WebSocket", "Dialer")
 	}
 
 	return &connection{

+ 2 - 2
transport/internet/websocket/hub.go

@@ -84,13 +84,13 @@ func (ln *Listener) listenws(address v2net.Address, port v2net.Port) error {
 	if ln.tlsConfig == nil {
 		l, err := net.Listen("tcp", netAddr)
 		if err != nil {
-			return errors.Base(err).Message("WebSocket|Listener: Failed to listen TCP ", netAddr)
+			return errors.New("failed to listen TCP ", netAddr).Base(err).Path("WebSocket", "Listener")
 		}
 		listener = l
 	} else {
 		l, err := tls.Listen("tcp", netAddr, ln.tlsConfig)
 		if err != nil {
-			return errors.Base(err).Message("WebSocket|Listener: Failed to listen TLS ", netAddr)
+			return errors.New("failed to listen TLS ", netAddr).Base(err).Path("WebSocket", "Listener")
 		}
 		listener = l
 	}

+ 4 - 4
v2ray.go

@@ -68,7 +68,7 @@ func newSimpleServer(config *Config) (*simpleServer, error) {
 			AccessLogType: log.LogType_None,
 		})
 		if err != nil {
-			return nil, errors.Base(err).Message("Core: Failed apply default log settings.")
+			return nil, errors.New("failed apply default log settings").Base(err).Path("Core")
 		}
 		space.AddApplication(l)
 	}
@@ -80,7 +80,7 @@ func newSimpleServer(config *Config) (*simpleServer, error) {
 			return nil, err
 		}
 		if err := space.AddApplication(o); err != nil {
-			return nil, errors.Base(err).Message("Core: Failed to add default outbound handler manager.")
+			return nil, errors.New("failed to add default outbound handler manager").Base(err).Path("Core")
 		}
 		outboundHandlerManager = o.(proxyman.OutboundHandlerManager)
 	}
@@ -92,7 +92,7 @@ func newSimpleServer(config *Config) (*simpleServer, error) {
 			return nil, err
 		}
 		if err := space.AddApplication(o); err != nil {
-			return nil, errors.Base(err).Message("Core: Failed to add default inbound handler manager.")
+			return nil, errors.New("failed to add default inbound handler manager").Base(err).Path("Core")
 		}
 		inboundHandlerManager = o.(proxyman.InboundHandlerManager)
 	}
@@ -147,7 +147,7 @@ func (s *simpleServer) Start() error {
 	if err := s.space.Start(); err != nil {
 		return err
 	}
-	log.Warning("V2Ray started.")
+	log.Trace(errors.New("V2Ray started").AtWarning())
 
 	return nil
 }