Liu Song’s Projects


~/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,