diff --git a/common/buf/buffer.go b/common/buf/buffer.go index 4306d05..6bcde17 100644 --- a/common/buf/buffer.go +++ b/common/buf/buffer.go @@ -2,7 +2,6 @@ package buf import ( "crypto/rand" - "fmt" "io" "net" "strconv" @@ -258,10 +257,6 @@ func (b *Buffer) WriteString(s string) (int, error) { return b.Write([]byte(s)) } -func (b *Buffer) WriteSprint(s ...any) (int, error) { - return b.WriteString(fmt.Sprint(s...)) -} - func (b *Buffer) WriteZero() error { if b.IsFull() { return io.ErrShortBuffer diff --git a/common/cache/lrucache.go b/common/cache/lrucache.go index edbe403..e3e1cf2 100644 --- a/common/cache/lrucache.go +++ b/common/cache/lrucache.go @@ -6,7 +6,7 @@ import ( "sync" "time" - "github.com/sagernet/sing/common/list" + "github.com/sagernet/sing/common/x/list" ) type Option[K comparable, V any] func(*LruCache[K, V]) diff --git a/common/exceptions/error.go b/common/exceptions/error.go index 5450b9f..8527b16 100644 --- a/common/exceptions/error.go +++ b/common/exceptions/error.go @@ -3,10 +3,11 @@ package exceptions import ( "context" "errors" - "fmt" "io" "net" "os" + + F "github.com/sagernet/sing/common/format" ) type causeError struct { @@ -42,15 +43,15 @@ func (e *extendedError) Unwrap() error { } func New(message ...any) error { - return errors.New(fmt.Sprint(message...)) + return errors.New(F.ToString(message...)) } func Cause(cause error, message ...any) error { - return &causeError{fmt.Sprint(message...), cause} + return &causeError{F.ToString(message...), cause} } func Extend(cause error, message ...any) error { - return &extendedError{fmt.Sprint(message...), cause} + return &extendedError{F.ToString(message...), cause} } type HasInnerError interface { diff --git a/common/format/fmt.go b/common/format/fmt.go new file mode 100644 index 0000000..dfd8976 --- /dev/null +++ b/common/format/fmt.go @@ -0,0 +1,54 @@ +package format + +import ( + "strconv" +) + +type Stringer interface { + String() string +} + +func ToString(messages ...any) string { + var output string + for _, rawMessage := range messages { + if rawMessage == nil { + output += "nil" + continue + } + switch message := rawMessage.(type) { + case string: + output += message + case bool: + if message { + output += "true" + } else { + output += "false" + } + case uint8: + output += strconv.FormatUint(uint64(message), 10) + case uint16: + output += strconv.FormatUint(uint64(message), 10) + case uint32: + output += strconv.FormatUint(uint64(message), 10) + case uint64: + output += strconv.FormatUint(message, 10) + case int8: + output += strconv.FormatInt(int64(message), 10) + case int16: + output += strconv.FormatInt(int64(message), 10) + case int32: + output += strconv.FormatInt(int64(message), 10) + case int64: + output += strconv.FormatInt(message, 10) + case uintptr: + output += strconv.FormatUint(uint64(message), 10) + case error: + output += message.Error() + case Stringer: + output += message.String() + default: + panic("unknown value") + } + } + return output +} diff --git a/common/net.go b/common/net.go index d454713..a8e4135 100644 --- a/common/net.go +++ b/common/net.go @@ -1,17 +1,9 @@ package common import ( - "os" "syscall" ) -func TryFileDescriptor(conn any) (uintptr, error) { - if rawConn, isRaw := conn.(syscall.Conn); isRaw { - return GetFileDescriptor(rawConn) - } - return 0, os.ErrInvalid -} - func GetFileDescriptor(conn syscall.Conn) (uintptr, error) { rawConn, err := conn.SyscallConn() if err != nil { diff --git a/common/network/http.go b/common/network/http.go deleted file mode 100644 index fa908fe..0000000 --- a/common/network/http.go +++ /dev/null @@ -1,41 +0,0 @@ -package network - -import ( - "context" - "io/ioutil" - "net" - "net/http" -) - -func HTTPClientWithNetwork(network string) *http.Client { - return &http.Client{ - Transport: &http.Transport{ - DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) { - var dialer net.Dialer - return dialer.DialContext(ctx, network, addr) - }, - }, - } -} - -func Get(url string) ([]byte, error) { - response, err := http.Get(url) - if err != nil { - return nil, err - } - defer response.Body.Close() - return ioutil.ReadAll(response.Body) -} - -func GetContext(ctx context.Context, client *http.Client, url string) ([]byte, error) { - request, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - response, err := client.Do(request) - if err != nil { - return nil, err - } - defer response.Body.Close() - return ioutil.ReadAll(response.Body) -} diff --git a/common/network/pem.go b/common/network/pem.go deleted file mode 100644 index c8accd7..0000000 --- a/common/network/pem.go +++ /dev/null @@ -1,23 +0,0 @@ -package network - -import ( - "crypto/ecdsa" - "crypto/rsa" - "crypto/x509" - "encoding/pem" -) - -func PEMBlock(data interface{}) *pem.Block { - var pemBlock *pem.Block - switch key := data.(type) { - case *ecdsa.PrivateKey: - keyBytes, _ := x509.MarshalECPrivateKey(key) - pemBlock = &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes} - case *rsa.PrivateKey: - pemBlock = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)} - case *x509.CertificateRequest: - pemBlock = &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: key.Raw} - } - - return pemBlock -} diff --git a/common/os.go b/common/os.go deleted file mode 100644 index 4e8771a..0000000 --- a/common/os.go +++ /dev/null @@ -1,52 +0,0 @@ -package common - -import ( - "encoding/json" - "io/ioutil" - "os" - "strings" -) - -func FileExists(path string) bool { - return Error(os.Stat(path)) == nil -} - -func WriteFile(path string, content []byte) error { - if strings.Contains(path, "/") { - parent := path[:strings.LastIndex(path, "/")] - if !FileExists(parent) { - err := os.MkdirAll(parent, 0o755) - if err != nil { - return err - } - } - } - - file, err := os.Create(path) - if err != nil { - return err - } - defer file.Close() - _, err = file.Write(content) - return err -} - -func ReadJSON(path string, data any) error { - content, err := ioutil.ReadFile(path) - if err != nil { - return err - } - err = json.Unmarshal(content, data) - if err != nil { - return err - } - return nil -} - -func WriteJSON(path string, data any) error { - content, err := json.Marshal(data) - if err != nil { - return err - } - return WriteFile(path, content) -} diff --git a/common/redir/tproxy_linux.go b/common/redir/tproxy_linux.go index 3c310c3..0984332 100644 --- a/common/redir/tproxy_linux.go +++ b/common/redir/tproxy_linux.go @@ -2,7 +2,6 @@ package redir import ( "encoding/binary" - "fmt" "net" "net/netip" "os" @@ -10,6 +9,7 @@ import ( "syscall" E "github.com/sagernet/sing/common/exceptions" + F "github.com/sagernet/sing/common/format" M "github.com/sagernet/sing/common/metadata" "golang.org/x/sys/unix" ) @@ -88,7 +88,7 @@ func DialUDP(network string, lAddr *net.UDPAddr, rAddr *net.UDPAddr) (*net.UDPCo return nil, err } - fdFile := os.NewFile(uintptr(fd), fmt.Sprintf("net-udp-dial-%s", rAddr.String())) + fdFile := os.NewFile(uintptr(fd), F.ToString("net-udp-dial-", rAddr)) defer fdFile.Close() c, err := net.FileConn(fdFile) diff --git a/common/x/list/README.md b/common/x/list/README.md new file mode 100644 index 0000000..0ac5af7 --- /dev/null +++ b/common/x/list/README.md @@ -0,0 +1,5 @@ +# x/list + +`list` with generic type + +upstream: go1.18 \ No newline at end of file diff --git a/common/list/cond.go b/common/x/list/cond.go similarity index 100% rename from common/list/cond.go rename to common/x/list/cond.go diff --git a/common/list/list.go b/common/x/list/list.go similarity index 100% rename from common/list/list.go rename to common/x/list/list.go diff --git a/go.mod b/go.mod index 5a21e74..fd587ee 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/sagernet/sing go 1.18 -require golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d +require golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c diff --git a/go.sum b/go.sum index 057668c..f140671 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/protocol/http/listener.go b/protocol/http/listener.go index 0cd0059..9a45fd6 100644 --- a/protocol/http/listener.go +++ b/protocol/http/listener.go @@ -4,7 +4,6 @@ import ( "bufio" "context" "encoding/base64" - "fmt" "net" "net/http" "strings" @@ -14,6 +13,7 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/auth" E "github.com/sagernet/sing/common/exceptions" + F "github.com/sagernet/sing/common/format" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" ) @@ -49,7 +49,7 @@ func HandleRequest(ctx context.Context, request *http.Request, conn net.Conn, au portStr = "80" } destination := M.ParseSocksaddrHostPortStr(request.URL.Hostname(), portStr) - _, err := fmt.Fprintf(conn, "HTTP/%d.%d %03d %s\r\n\r\n", request.ProtoMajor, request.ProtoMinor, http.StatusOK, "Connection established") + _, err := conn.Write([]byte(F.ToString("HTTP/", request.ProtoMajor, ".", request.ProtoMinor, " 200 Connection established\r\n\r\n"))) if err != nil { return E.Cause(err, "write http response") } diff --git a/protocol/trojan/service.go b/protocol/trojan/service.go index 72b3096..81b5c8d 100644 --- a/protocol/trojan/service.go +++ b/protocol/trojan/service.go @@ -2,13 +2,13 @@ package trojan import ( "context" - "fmt" "io" "net" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" E "github.com/sagernet/sing/common/exceptions" + F "github.com/sagernet/sing/common/format" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/rw" @@ -156,7 +156,7 @@ type Error struct { } func (e *Error) Error() string { - return fmt.Sprint("process connection from ", e.Metadata.Source, ": ", e.Inner.Error()) + return F.ToString("process connection from ", e.Metadata.Source, ": ", e.Inner) } func (e *Error) Unwrap() error {