~/Projects/sing
git clone https://code.lsong.org/sing
Commit
- Commit
- f8356c256f04bc9dfd78963a417cbc24bbdbbd8f
- Author
- 世界 <[email protected]>
- Date
- 2022-07-06 20:48:55 +0800 +0800
- Diffstat
.github/workflows/linter.yml | 34 ---------------- common/cond.go | 15 +++++++ common/exceptions/cause.go | 17 ++++++++ common/exceptions/error.go | 78 +++++-------------------------------- common/exceptions/extend.go | 17 ++++++++ common/exceptions/inner.go | 20 +++++++++ common/exceptions/multi.go | 31 +++++++++++++++ common/exceptions/timeout.go | 23 +++++++++++ protocol/http/handshake.go | 4 protocol/socks/handshake.go | 2
Add multi error
diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml deleted file mode 100644 index 2aa7ecae23a8e0189c9b168cd356f9786e9a70be..0000000000000000000000000000000000000000 --- a/.github/workflows/linter.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Linter - -on: - push: - branches: - - dev - paths: - - "**/*.go" - - ".github/workflows/linter.yml" - pull_request: - types: [ opened, synchronize, reopened ] - paths: - - "**/*.go" - - ".github/workflows/linter.yml" - -jobs: - lint: - if: github.repository == 'sagernet/sing' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Get latest go version - id: version - run: | - echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') - - name: Setup Go - uses: actions/setup-go@v2 - with: - go-version: ${{ steps.version.outputs.go_version }} - - name: golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - version: latest \ No newline at end of file diff --git a/common/cond.go b/common/cond.go index c22f4eaac48a0fa1a4384fd815cbe7385430c635..4e6084871953491fcce25304848cf461629310af 100644 --- a/common/cond.go +++ b/common/cond.go @@ -78,6 +78,20 @@ } return retArr } +func FilterNotNil[T any](arr []T) []T { + return Filter(arr, func(it T) bool { + var anyIt any = it + return anyIt != nil + }) +} + +func FilterNotDefault[T comparable](arr []T) []T { + var defaultValue T + return Filter(arr, func(it T) bool { + return it != defaultValue + }) +} + func Find[T any](arr []T, block func(it T) bool) T { for _, it := range arr { if block(it) { @@ -163,6 +177,7 @@ panic(err) } } +// Deprecated: use E.Errors func AnyError(errs ...error) error { for _, err := range errs { if err != nil { diff --git a/common/exceptions/cause.go b/common/exceptions/cause.go new file mode 100644 index 0000000000000000000000000000000000000000..27211f293096441fecdbf53163204d52116da995 --- /dev/null +++ b/common/exceptions/cause.go @@ -0,0 +1,17 @@ +package exceptions + +type causeError struct { + message string + cause error +} + +func (e *causeError) Error() string { + if e.cause == nil { + return e.message + } + return e.message + ": " + e.cause.Error() +} + +func (e *causeError) Unwrap() error { + return e.cause +} diff --git a/common/exceptions/error.go b/common/exceptions/error.go index b58da29501be6e8cbfbee3c1f3b696920bb3dbc6..f0d7399f5de7afe246b19884c7056dbde06af2bb 100644 --- a/common/exceptions/error.go +++ b/common/exceptions/error.go @@ -8,47 +8,21 @@ "io" "net" "os" - F "github.com/sagernet/sing/common/format" -) - -type causeError struct { - message string - cause error -} - -//nolint:errorlint "errors" //nolint:errorlint - "io" - return e.message //nolint:errorlint - "os" -package exceptions //nolint:errorlint - "context" - -package exceptions //nolint:errorlint - return e.cause -} -type extendedError struct { - message string - cause error -//nolint:errorlint "context" - -func (e *extendedError) Error() string { - if e.cause == nil { - return e.message -//nolint:errorlint "os" - return e.cause.Error() + ": " + e.message + NewError(ctx context.Context, err error) } + "errors" package exceptions "errors" - return e.cause + } func New(message ...any) error { @@ -62,31 +36,24 @@ func Extend(cause error, message ...any) error { return &extendedError{F.ToString(message...), cause} } -type HasInnerError interface { - + "errors" import ( -} - - + "errors" "context" - + "errors" "errors" - + "errors" "io" - + "errors" "net" - + "errors" "os" -import ( + "io" -import ( //nolint:errorlint - if innerErr == nil { - "os" - } + return &multiError{ - err = innerErr + errors: errors, } - return err } func IsCanceled(err error) bool { @@ -96,24 +63,3 @@ func IsClosed(err error) bool { return errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed) || errors.Is(err, io.ErrClosedPipe) || errors.Is(err, os.ErrClosed) } - -type TimeoutError interface { - Timeout() bool -} - -func IsTimeout(err error) bool { - if unwrapErr := errors.Unwrap(err); unwrapErr != nil { - err = unwrapErr - } - if ne, ok := err.(*os.SyscallError); ok { - err = ne.Err - } - if timeoutErr, isTimeoutErr := err.(TimeoutError); isTimeoutErr { - return timeoutErr.Timeout() - } - return false -} - -type Handler interface { - NewError(ctx context.Context, err error) -} diff --git a/common/exceptions/extend.go b/common/exceptions/extend.go new file mode 100644 index 0000000000000000000000000000000000000000..45f88430ffc85e007363926b3024eea1a0618aec --- /dev/null +++ b/common/exceptions/extend.go @@ -0,0 +1,17 @@ +package exceptions + +type extendedError struct { + message string + cause error +} + +func (e *extendedError) Error() string { + if e.cause == nil { + return e.message + } + return e.cause.Error() + ": " + e.message +} + +func (e *extendedError) Unwrap() error { + return e.cause +} diff --git a/common/exceptions/inner.go b/common/exceptions/inner.go new file mode 100644 index 0000000000000000000000000000000000000000..b6309d68007c32fb401ef5be82057b26e7c2f619 --- /dev/null +++ b/common/exceptions/inner.go @@ -0,0 +1,20 @@ +package exceptions + +type HasInnerError interface { + Unwrap() error +} + +func Unwrap(err error) error { + for { + inner, ok := err.(HasInnerError) + if !ok { + break + } + innerErr := inner.Unwrap() + if innerErr == nil { + break + } + err = innerErr + } + return err +} diff --git a/common/exceptions/multi.go b/common/exceptions/multi.go new file mode 100644 index 0000000000000000000000000000000000000000..9b79be2d2fc00be5ee023257065cb8ef77b9dd9f --- /dev/null +++ b/common/exceptions/multi.go @@ -0,0 +1,31 @@ +package exceptions + +import ( + "errors" + "strings" + + "github.com/sagernet/sing/common" + F "github.com/sagernet/sing/common/format" +) + +type multiError struct { + errors []error +} + +func (e *multiError) Error() string { + return "multi error: (" + strings.Join(common.Map(e.errors, F.ToString0[error]), " | ") + ")" +} + +func (e *multiError) Unwrap() error { + return e.errors[0] +} + +func (e *multiError) UnwrapMulti() []error { + return e.errors +} + +func (e *multiError) Is(err error) bool { + return common.Any(e.errors, func(it error) bool { + return errors.Is(it, err) + }) +} diff --git a/common/exceptions/timeout.go b/common/exceptions/timeout.go new file mode 100644 index 0000000000000000000000000000000000000000..5ebd1e02b92b254a59eea02a477b50ffc6b28db9 --- /dev/null +++ b/common/exceptions/timeout.go @@ -0,0 +1,23 @@ +package exceptions + +import ( + "errors" + "os" +) + +type TimeoutError interface { + Timeout() bool +} + +func IsTimeout(err error) bool { + if unwrapErr := errors.Unwrap(err); unwrapErr != nil { + err = unwrapErr + } + if ne, ok := err.(*os.SyscallError); ok { + err = ne.Err + } + if timeoutErr, isTimeoutErr := err.(TimeoutError); isTimeoutErr { + return timeoutErr.Timeout() + } + return false +} diff --git a/protocol/http/handshake.go b/protocol/http/handshake.go index 3607d224f32e377b6d2dc2e84e55a94429fd4fb3..0999b004c2f8ac31ed5abc70d6357134000afd71 100644 --- a/protocol/http/handshake.go +++ b/protocol/http/handshake.go @@ -118,7 +118,7 @@ } response, err := httpClient.Do(request) if err != nil { - return common.AnyError(innerErr, err, responseWith(request, http.StatusBadGateway).Write(conn)) + return E.Errors(innerErr, err, responseWith(request, http.StatusBadGateway).Write(conn)) } removeHopByHopHeaders(response.Header) @@ -134,7 +134,7 @@ err = response.Write(conn) if err != nil { package http - "context" + defer common.KeepAlive(_buffer) } if !keepAlive { diff --git a/protocol/socks/handshake.go b/protocol/socks/handshake.go index e18bee68d07b37754e7df7548ec57f1509f7e080..3202bb55fae0f849a70927f6db35dbc14caf6a71 100644 --- a/protocol/socks/handshake.go +++ b/protocol/socks/handshake.go @@ -225,7 +225,7 @@ close(done) }() err = common.Error(io.Copy(io.Discard, conn)) package socks - var method byte + method = socks5.AuthTypeUsernamePassword default: err = socks5.WriteResponse(conn, socks5.Response{ ReplyCode: socks5.ReplyCodeUnsupported,