mirror of https://github.com/v2ray/v2ray-core
smart error propagation
parent
0f71305ee1
commit
e480091388
|
@ -11,6 +11,7 @@ import (
|
|||
"v2ray.com/core/app/dispatcher"
|
||||
"v2ray.com/core/app/log"
|
||||
"v2ray.com/core/common/buf"
|
||||
"v2ray.com/core/common/errors"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/transport/internet"
|
||||
|
@ -53,7 +54,12 @@ 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 {
|
||||
log.Info("Proxyman|TCPWorker: Connection ends with ", err)
|
||||
err := errors.Base(err).Message("Proxyman|TCPWorker: Connection ends.")
|
||||
if errors.IsActionRequired(err) {
|
||||
log.Warning(err)
|
||||
} else {
|
||||
log.Info(err)
|
||||
}
|
||||
}
|
||||
cancel()
|
||||
conn.Close()
|
||||
|
@ -213,7 +219,12 @@ 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 {
|
||||
log.Info("Proxyman|UDPWorker: Connection ends with ", err)
|
||||
err = errors.Base(err).Message("Proxyman|UDPWorker: Connection ends.")
|
||||
if errors.IsActionRequired(err) {
|
||||
log.Warning(err)
|
||||
} else {
|
||||
log.Info(err)
|
||||
}
|
||||
}
|
||||
w.removeConn(source)
|
||||
cancel()
|
||||
|
|
|
@ -67,7 +67,12 @@ func (h *Handler) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) {
|
|||
err := h.proxy.Process(ctx, outboundRay, h)
|
||||
// Ensure outbound ray is properly closed.
|
||||
if err != nil && errors.Cause(err) != io.EOF {
|
||||
log.Info("Proxyman|OutboundHandler: Failed to process outbound traffic: ", err)
|
||||
err = errors.Base(err).Message("Proxyman|OutboundHandler: Failed to process outbound traffic.")
|
||||
if errors.IsActionRequired(err) {
|
||||
log.Warning(err)
|
||||
} else {
|
||||
log.Info(err)
|
||||
}
|
||||
outboundRay.OutboundOutput().CloseError()
|
||||
} else {
|
||||
outboundRay.OutboundOutput().Close()
|
||||
|
|
|
@ -12,10 +12,15 @@ type hasInnerError interface {
|
|||
Inner() error
|
||||
}
|
||||
|
||||
type actionRequired interface {
|
||||
ActionRequired() bool
|
||||
}
|
||||
|
||||
// Error is an error object with underlying error.
|
||||
type Error struct {
|
||||
message string
|
||||
inner error
|
||||
message string
|
||||
inner error
|
||||
actionRequired bool
|
||||
}
|
||||
|
||||
// Error implements error.Error().
|
||||
|
@ -31,6 +36,10 @@ func (v *Error) Inner() error {
|
|||
return v.inner
|
||||
}
|
||||
|
||||
func (v *Error) ActionRequired() bool {
|
||||
return v.actionRequired
|
||||
}
|
||||
|
||||
// New returns a new error object with message formed from given arguments.
|
||||
func New(msg ...interface{}) error {
|
||||
return &Error{
|
||||
|
@ -56,10 +65,7 @@ func Cause(err error) error {
|
|||
}
|
||||
for {
|
||||
inner, ok := err.(hasInnerError)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
if inner.Inner() == nil {
|
||||
if !ok || inner.Inner() == nil {
|
||||
break
|
||||
}
|
||||
err = inner.Inner()
|
||||
|
@ -67,8 +73,28 @@ 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()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ErrorBuilder struct {
|
||||
error
|
||||
actionRequired bool
|
||||
}
|
||||
|
||||
func (v ErrorBuilder) RequireUserAction() ErrorBuilder {
|
||||
v.actionRequired = true
|
||||
return v
|
||||
}
|
||||
|
||||
// Message returns an error object with given message and base error.
|
||||
|
@ -78,8 +104,9 @@ func (v ErrorBuilder) Message(msg ...interface{}) error {
|
|||
}
|
||||
|
||||
return &Error{
|
||||
message: serial.Concat(msg...) + " > " + v.error.Error(),
|
||||
inner: v.error,
|
||||
message: serial.Concat(msg...) + " > " + v.error.Error(),
|
||||
inner: v.error,
|
||||
actionRequired: v.actionRequired,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +116,8 @@ func (v ErrorBuilder) Format(format string, values ...interface{}) error {
|
|||
return nil
|
||||
}
|
||||
return &Error{
|
||||
message: fmt.Sprintf(format, values...) + " > " + v.error.Error(),
|
||||
inner: v.error,
|
||||
message: fmt.Sprintf(format, values...) + " > " + v.error.Error(),
|
||||
inner: v.error,
|
||||
actionRequired: v.actionRequired,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package errors_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
. "v2ray.com/core/common/errors"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestActionRequired(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
err := New("TestError")
|
||||
assert.Bool(IsActionRequired(err)).IsFalse()
|
||||
|
||||
err = Base(io.EOF).Message("TestError2")
|
||||
assert.Bool(IsActionRequired(err)).IsFalse()
|
||||
|
||||
err = Base(io.EOF).RequireUserAction().Message("TestError3")
|
||||
assert.Bool(IsActionRequired(err)).IsTrue()
|
||||
|
||||
err = Base(io.EOF).RequireUserAction().Message("TestError4")
|
||||
err = Base(err).Message("TestError5")
|
||||
assert.Bool(IsActionRequired(err)).IsTrue()
|
||||
}
|
|
@ -60,7 +60,7 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale
|
|||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Base(err).Message("Shadowsocks|Client: Failed to find an available destination.")
|
||||
return errors.Base(err).RequireUserAction().Message("Shadowsocks|Client: Failed to find an available destination.")
|
||||
}
|
||||
log.Info("Shadowsocks|Client: Tunneling request to ", destination, " via ", server.Destination())
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
|
|||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Base(err).Message("VMess|Outbound: Failed to find an available destination.")
|
||||
return errors.Base(err).RequireUserAction().Message("VMess|Outbound: Failed to find an available destination.")
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package internet
|
|||
import (
|
||||
"net"
|
||||
|
||||
"v2ray.com/core/app/log"
|
||||
"v2ray.com/core/common/errors"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/retry"
|
||||
|
@ -85,13 +86,21 @@ func (v *TCPHub) start() {
|
|||
default:
|
||||
conn, err := v.listener.Accept()
|
||||
if err != nil {
|
||||
return errors.Base(err).Message("Internet|Listener: Failed to accept new TCP connection.")
|
||||
return errors.Base(err).RequireUserAction().Message("Internet|Listener: Failed to accept new TCP connection.")
|
||||
}
|
||||
newConn = conn
|
||||
return nil
|
||||
}
|
||||
})
|
||||
if err == nil && newConn != nil {
|
||||
if err != nil {
|
||||
if errors.IsActionRequired(err) {
|
||||
log.Warning(err)
|
||||
} else {
|
||||
log.Info(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if newConn != nil {
|
||||
go v.connCallback(newConn)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue