diff --git a/common/bufio/conn.go b/common/bufio/conn.go index ad3d722..ffa83ea 100644 --- a/common/bufio/conn.go +++ b/common/bufio/conn.go @@ -9,6 +9,7 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" + E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/rw" @@ -37,6 +38,11 @@ func needReadFromWrapper(dst io.ReaderFrom, src io.Reader) bool { } func Copy(dst io.Writer, src io.Reader) (n int64, err error) { + if src == nil { + return 0, E.New("nil reader") + } else if dst == nil { + return 0, E.New("nil writer") + } src = N.UnwrapReader(src) dst = N.UnwrapWriter(dst) if wt, ok := src.(io.WriterTo); ok { diff --git a/common/exceptions/error.go b/common/exceptions/error.go index 0e33c6a..fb9316c 100644 --- a/common/exceptions/error.go +++ b/common/exceptions/error.go @@ -6,10 +6,11 @@ import ( "io" "net" "os" + "syscall" + _ "unsafe" "github.com/sagernet/sing/common" F "github.com/sagernet/sing/common/format" - "syscall" ) type Handler interface { @@ -45,10 +46,17 @@ func Errors(errors ...error) error { } } -func IsCanceled(err error) bool { - return IsMulti(err, context.Canceled, context.DeadlineExceeded) +//go:linkname errCanceled net.errCanceled +var errCanceled error + +func IsClosedOrCanceled(err error) bool { + return IsMulti(err, io.EOF, net.ErrClosed, io.ErrClosedPipe, os.ErrClosed, syscall.EPIPE, syscall.ECONNRESET, context.Canceled, context.DeadlineExceeded, errCanceled) } func IsClosed(err error) bool { - return IsMulti(err, io.EOF, net.ErrClosed, io.ErrClosedPipe, os.ErrClosed, syscall.EPIPE) + return IsMulti(err, io.EOF, net.ErrClosed, io.ErrClosedPipe, os.ErrClosed, syscall.EPIPE, syscall.ECONNRESET) +} + +func IsCanceled(err error) bool { + return IsMulti(err, context.Canceled, context.DeadlineExceeded, errCanceled) }