Refactor log (#3446)

* Refactor log

* Add new log methods

* Fix logger test

* Change all logging code

* Clean up pathObj

* Rebase to latest main

* Remove invoking method name after the dot
This commit is contained in:
yuhan6665 2024-06-29 14:32:57 -04:00 committed by GitHub
parent 8320732743
commit 079d0bd8a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
291 changed files with 1837 additions and 2368 deletions

View file

@ -4,6 +4,7 @@ import (
"io"
"github.com/xtls/xray-core/common/bytespool"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
)
@ -226,7 +227,7 @@ func (b *Buffer) Write(data []byte) (int, error) {
// WriteByte writes a single byte into the buffer.
func (b *Buffer) WriteByte(v byte) error {
if b.IsFull() {
return newError("buffer full")
return errors.New("buffer full")
}
b.v[b.end] = v
b.end++
@ -286,7 +287,7 @@ func (b *Buffer) ReadFullFrom(reader io.Reader, size int32) (int64, error) {
end := b.end + size
if end > int32(len(b.v)) {
v := end
return 0, newError("out of bound: ", v)
return 0, errors.New("out of bound: ", v)
}
n, err := io.ReadFull(reader, b.v[b.end:end])
b.end += int32(n)

View file

@ -120,7 +120,7 @@ func Copy(reader Reader, writer Writer, options ...CopyOption) error {
return nil
}
var ErrNotTimeoutReader = newError("not a TimeoutReader")
var ErrNotTimeoutReader = errors.New("not a TimeoutReader")
func CopyOnceTimeout(reader Reader, writer Writer, timeout time.Duration) error {
timeoutReader, ok := reader.(TimeoutReader)

View file

@ -27,7 +27,7 @@ func TestReadError(t *testing.T) {
t.Error("expected to be ReadError, but not")
}
if err.Error() != "error" {
if err.Error() != "common/buf_test: error" {
t.Fatal("unexpected error message: ", err.Error())
}
}
@ -48,7 +48,7 @@ func TestWriteError(t *testing.T) {
t.Error("expected to be WriteError, but not")
}
if err.Error() != "error" {
if err.Error() != "common/buf_test: error" {
t.Fatal("unexpected error message: ", err.Error())
}
}

View file

@ -1,9 +0,0 @@
package buf
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -1,12 +1,14 @@
package buf
import (
"context"
"io"
"net"
"os"
"syscall"
"time"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/transport/internet/stat"
)
@ -18,7 +20,7 @@ type Reader interface {
}
// ErrReadTimeout is an error that happens with IO timeout.
var ErrReadTimeout = newError("IO timeout")
var ErrReadTimeout = errors.New("IO timeout")
// TimeoutReader is a reader that returns error if Read() operation takes longer than the given timeout.
type TimeoutReader interface {
@ -74,7 +76,7 @@ func NewReader(reader io.Reader) Reader {
if sc, ok := reader.(syscall.Conn); ok {
rawConn, err := sc.SyscallConn()
if err != nil {
newError("failed to get sysconn").Base(err).WriteToLog()
errors.LogInfoInner(context.Background(), err, "failed to get sysconn")
} else {
var counter stats.Counter

View file

@ -21,7 +21,7 @@ func readOneUDP(r io.Reader) (*Buffer, error) {
}
b.Release()
return nil, newError("Reader returns too many empty payloads.")
return nil, errors.New("Reader returns too many empty payloads.")
}
// ReadBuffer reads a Buffer from the given reader.

View file

@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/bytespool"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/protocol"
)
@ -63,7 +64,7 @@ type AEADAuthenticator struct {
func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
iv := v.NonceGenerator()
if len(iv) != v.AEAD.NonceSize() {
return nil, newError("invalid AEAD nonce size: ", len(iv))
return nil, errors.New("invalid AEAD nonce size: ", len(iv))
}
var additionalData []byte
@ -76,7 +77,7 @@ func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) {
iv := v.NonceGenerator()
if len(iv) != v.AEAD.NonceSize() {
return nil, newError("invalid AEAD nonce size: ", len(iv))
return nil, errors.New("invalid AEAD nonce size: ", len(iv))
}
var additionalData []byte
@ -131,7 +132,7 @@ func (r *AuthenticationReader) readSize() (uint16, uint16, error) {
return size, padding, err
}
var errSoft = newError("waiting for more data")
var errSoft = errors.New("waiting for more data")
func (r *AuthenticationReader) readBuffer(size int32, padding int32) (*buf.Buffer, error) {
b := buf.New()
@ -255,7 +256,7 @@ func (w *AuthenticationWriter) seal(b []byte) (*buf.Buffer, error) {
sizeBytes := w.sizeParser.SizeBytes()
totalSize := sizeBytes + encryptedSize + paddingSize
if totalSize > buf.Size {
return nil, newError("size too large: ", totalSize)
return nil, errors.New("size too large: ", totalSize)
}
eb := buf.New()

View file

@ -1,9 +0,0 @@
package crypto
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

25
common/ctx/context.go Normal file
View file

@ -0,0 +1,25 @@
package ctx
import "context"
type SessionKey int
// ID of a session.
type ID uint32
const(
idSessionKey SessionKey = 0
)
// ContextWithID returns a new context with the given ID.
func ContextWithID(ctx context.Context, id ID) context.Context {
return context.WithValue(ctx, idSessionKey, id)
}
// IDFromContext returns ID in this context, or 0 if not contained.
func IDFromContext(ctx context.Context) ID {
if id, ok := ctx.Value(idSessionKey).(ID); ok {
return id
}
return 0
}

View file

@ -4,6 +4,7 @@ import (
"io"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
)
type BehaviorSeedLimitedDrainer struct {
@ -27,9 +28,9 @@ func (d *BehaviorSeedLimitedDrainer) Drain(reader io.Reader) error {
if d.DrainSize > 0 {
err := drainReadN(reader, d.DrainSize)
if err == nil {
return newError("drained connection")
return errors.New("drained connection")
}
return newError("unable to drain connection").Base(err)
return errors.New("unable to drain connection").Base(err)
}
return nil
}
@ -44,7 +45,7 @@ func WithError(drainer Drainer, reader io.Reader, err error) error {
if drainErr == nil {
return err
}
return newError(drainErr).Base(err)
return errors.New(drainErr).Base(err)
}
type NopDrainer struct{}

View file

@ -1,9 +0,0 @@
package drain
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -1,9 +0,0 @@
package common
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -1,37 +0,0 @@
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
pwd, err := os.Getwd()
if err != nil {
fmt.Println("can not get current working directory")
os.Exit(1)
}
pkg := filepath.Base(pwd)
if pkg == "xray-core" {
pkg = "core"
}
file, err := os.OpenFile("errors.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644)
if err != nil {
fmt.Printf("Failed to generate errors.generated.go: %v", err)
os.Exit(1)
}
defer file.Close()
fmt.Fprintf(file, `package %s
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}
`, pkg)
}

View file

@ -2,9 +2,11 @@
package errors // import "github.com/xtls/xray-core/common/errors"
import (
"reflect"
"context"
"runtime"
"strings"
c "github.com/xtls/xray-core/common/ctx"
"github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/serial"
)
@ -22,29 +24,13 @@ type hasSeverity interface {
// Error is an error object with underlying error.
type Error struct {
pathObj interface{}
prefix []interface{}
message []interface{}
caller string
inner error
severity log.Severity
}
func (err *Error) WithPathObj(obj interface{}) *Error {
err.pathObj = obj
return err
}
func (err *Error) pkgPath() string {
if err.pathObj == nil {
return ""
}
path := reflect.TypeOf(err.pathObj).PkgPath()
if len(path) >= trim {
return path[trim:]
}
return path
}
// Error implements error.Error().
func (err *Error) Error() string {
builder := strings.Builder{}
@ -54,9 +40,8 @@ func (err *Error) Error() string {
builder.WriteString("] ")
}
path := err.pkgPath()
if len(path) > 0 {
builder.WriteString(path)
if len(err.caller) > 0 {
builder.WriteString(err.caller)
builder.WriteString(": ")
}
@ -129,24 +114,6 @@ func (err *Error) String() string {
return err.Error()
}
// WriteToLog writes current error into log.
func (err *Error) WriteToLog(opts ...ExportOption) {
var holder ExportOptionHolder
for _, opt := range opts {
opt(&holder)
}
if holder.SessionID > 0 {
err.prefix = append(err.prefix, holder.SessionID)
}
log.Record(&log.GeneralMessage{
Severity: GetSeverity(err),
Content: err,
})
}
type ExportOptionHolder struct {
SessionID uint32
}
@ -155,12 +122,82 @@ type ExportOption func(*ExportOptionHolder)
// New returns a new error object with message formed from given arguments.
func New(msg ...interface{}) *Error {
pc, _, _, _ := runtime.Caller(1)
details := runtime.FuncForPC(pc).Name()
if len(details) >= trim {
details = details[trim:]
}
i := strings.Index(details, ".")
if i > 0 {
details = details[:i]
}
return &Error{
message: msg,
severity: log.Severity_Info,
caller: details,
}
}
func LogDebug(ctx context.Context, msg ...interface{}) {
doLog(ctx, nil, log.Severity_Debug, msg...)
}
func LogDebugInner(ctx context.Context, inner error, msg ...interface{}) {
doLog(ctx, inner, log.Severity_Debug, msg...)
}
func LogInfo(ctx context.Context, msg ...interface{}) {
doLog(ctx, nil, log.Severity_Info, msg...)
}
func LogInfoInner(ctx context.Context, inner error, msg ...interface{}) {
doLog(ctx, inner, log.Severity_Debug, msg...)
}
func LogWarning(ctx context.Context, msg ...interface{}) {
doLog(ctx, nil, log.Severity_Warning, msg...)
}
func LogWarningInner(ctx context.Context, inner error, msg ...interface{}) {
doLog(ctx, inner, log.Severity_Debug, msg...)
}
func LogError(ctx context.Context, msg ...interface{}) {
doLog(ctx, nil, log.Severity_Error, msg...)
}
func LogErrorInner(ctx context.Context, inner error, msg ...interface{}) {
doLog(ctx, inner, log.Severity_Debug, msg...)
}
func doLog(ctx context.Context, inner error, severity log.Severity, msg ...interface{}) {
pc, _, _, _ := runtime.Caller(2)
details := runtime.FuncForPC(pc).Name()
if len(details) >= trim {
details = details[trim:]
}
i := strings.Index(details, ".")
if i > 0 {
details = details[:i]
}
err := &Error{
message: msg,
severity: severity,
caller: details,
inner: inner,
}
if ctx != nil && ctx != context.Background() {
id := uint32(c.IDFromContext(ctx))
if id > 0 {
err.prefix = append(err.prefix, id)
}
}
log.Record(&log.GeneralMessage{
Severity: GetSeverity(err),
Content: err,
})
}
// Cause returns the root cause of this error.
func Cause(err error) error {
if err == nil {

View file

@ -36,20 +36,14 @@ func TestError(t *testing.T) {
}
}
type e struct{}
func TestErrorMessage(t *testing.T) {
data := []struct {
err error
msg string
}{
{
err: New("a").Base(New("b")).WithPathObj(e{}),
msg: "common/errors_test: a > b",
},
{
err: New("a").Base(New("b").WithPathObj(e{})),
msg: "a > common/errors_test: b",
err: New("a").Base(New("b")),
msg: "common/errors_test: a > common/errors_test: b",
},
}

View file

@ -37,7 +37,7 @@ func (m *ClientManager) Dispatch(ctx context.Context, link *transport.Link) erro
}
}
return newError("unable to find an available mux client").AtWarning()
return errors.New("unable to find an available mux client").AtWarning()
}
type WorkerPicker interface {
@ -57,7 +57,7 @@ func (p *IncrementalWorkerPicker) cleanupFunc() error {
defer p.access.Unlock()
if len(p.workers) == 0 {
return newError("no worker")
return errors.New("no worker")
}
p.cleanup()
@ -155,7 +155,7 @@ func (f *DialingWorkerFactory) Create() (*ClientWorker, error) {
ctx, cancel := context.WithCancel(ctx)
if err := p.Process(ctx, &transport.Link{Reader: uplinkReader, Writer: downlinkWriter}, d); err != nil {
errors.New("failed to handler mux client connection").Base(err).WriteToLog()
errors.LogInfoInner(ctx, err, "failed to handler mux client connection")
}
common.Must(c.Close())
cancel()
@ -244,7 +244,7 @@ func writeFirstPayload(reader buf.Reader, writer *Writer) error {
func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1]
ob := outbounds[len(outbounds)-1]
transferType := protocol.TransferTypeStream
if ob.Target.Network == net.Network_UDP {
transferType = protocol.TransferTypePacket
@ -254,15 +254,15 @@ func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
defer s.Close(false)
defer writer.Close()
newError("dispatching request to ", ob.Target).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "dispatching request to ", ob.Target)
if err := writeFirstPayload(s.input, writer); err != nil {
newError("failed to write first payload").Base(err).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfoInner(ctx, err, "failed to write first payload")
writer.hasError = true
return
}
if err := buf.Copy(s.input, writer); err != nil {
newError("failed to fetch all input").Base(err).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfoInner(ctx, err, "failed to fetch all input")
writer.hasError = true
return
}
@ -335,7 +335,7 @@ func (m *ClientWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
rr := s.NewReader(reader, &meta.Target)
err := buf.Copy(rr, s.output)
if err != nil && buf.IsWriteError(err) {
newError("failed to write to downstream. closing session ", s.ID).Base(err).WriteToLog()
errors.LogInfoInner(context.Background(), err, "failed to write to downstream. closing session ", s.ID)
s.Close(false)
return buf.Copy(rr, buf.Discard)
}
@ -365,7 +365,7 @@ func (m *ClientWorker) fetchOutput() {
err := meta.Unmarshal(reader)
if err != nil {
if errors.Cause(err) != io.EOF {
newError("failed to read metadata").Base(err).WriteToLog()
errors.LogInfoInner(context.Background(), err, "failed to read metadata")
}
break
}
@ -381,12 +381,12 @@ func (m *ClientWorker) fetchOutput() {
err = m.handleStatusKeep(&meta, reader)
default:
status := meta.SessionStatus
newError("unknown status: ", status).AtError().WriteToLog()
errors.LogError(context.Background(), "unknown status: ", status)
return
}
if err != nil {
newError("failed to process data").Base(err).WriteToLog()
errors.LogInfoInner(context.Background(), err, "failed to process data")
return
}
}

View file

@ -1,9 +0,0 @@
package mux
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/bitmask"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
@ -102,7 +103,7 @@ func (f *FrameMetadata) Unmarshal(reader io.Reader) error {
return err
}
if metaLen > 512 {
return newError("invalid metalen ", metaLen).AtError()
return errors.New("invalid metalen ", metaLen).AtError()
}
b := buf.New()
@ -118,7 +119,7 @@ func (f *FrameMetadata) Unmarshal(reader io.Reader) error {
// Visible for testing only.
func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
if b.Len() < 4 {
return newError("insufficient buffer: ", b.Len())
return errors.New("insufficient buffer: ", b.Len())
}
f.SessionID = binary.BigEndian.Uint16(b.BytesTo(2))
@ -129,14 +130,14 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
if f.SessionStatus == SessionStatusNew || (f.SessionStatus == SessionStatusKeep && b.Len() > 4 &&
TargetNetwork(b.Byte(4)) == TargetNetworkUDP) { // MUST check the flag first
if b.Len() < 8 {
return newError("insufficient buffer: ", b.Len())
return errors.New("insufficient buffer: ", b.Len())
}
network := TargetNetwork(b.Byte(4))
b.Advance(5)
addr, port, err := addrParser.ReadAddressPort(nil, b)
if err != nil {
return newError("failed to parse address and port").Base(err)
return errors.New("failed to parse address and port").Base(err)
}
switch network {
@ -145,7 +146,7 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
case TargetNetworkUDP:
f.Target = net.UDPDestination(addr, port)
default:
return newError("unknown network type: ", network)
return errors.New("unknown network type: ", network)
}
}

View file

@ -5,6 +5,7 @@ import (
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/serial"
)
@ -37,7 +38,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
}
if size > buf.Size {
return nil, newError("packet size too large: ", size)
return nil, errors.New("packet size too large: ", size)
}
b := buf.New()

View file

@ -94,7 +94,7 @@ func NewServerWorker(ctx context.Context, d routing.Dispatcher, link *transport.
func handle(ctx context.Context, s *Session, output buf.Writer) {
writer := NewResponseWriter(s.ID, output, s.transferType)
if err := buf.Copy(s.input, writer); err != nil {
newError("session ", s.ID, " ends.").Base(err).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfoInner(ctx, err, "session ", s.ID, " ends.")
writer.hasError = true
}
@ -118,7 +118,7 @@ func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.Bu
}
func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error {
newError("received request for ", meta.Target).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "received request for ", meta.Target)
{
msg := &log.AccessMessage{
To: meta.Target,
@ -134,7 +134,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
if network := session.AllowedNetworkFromContext(ctx); network != net.Network_Unknown {
if meta.Target.Network != network {
return newError("unexpected network ", meta.Target.Network) // it will break the whole Mux connection
return errors.New("unexpected network ", meta.Target.Network) // it will break the whole Mux connection
}
}
@ -152,7 +152,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
} else {
if x.Status == Initializing { // nearly impossible
XUDPManager.Unlock()
newError("XUDP hit ", meta.GlobalID).Base(errors.New("conflict")).AtWarning().WriteToLog(session.ExportIDToError(ctx))
errors.LogWarningInner(ctx, errors.New("conflict"), "XUDP hit ", meta.GlobalID)
// It's not a good idea to return an err here, so just let client wait.
// Client will receive an End frame after sending a Keep frame.
return nil
@ -170,7 +170,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
b.Release()
mb = nil
}
newError("XUDP hit ", meta.GlobalID).Base(err).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfoInner(ctx, err,"XUDP hit ", meta.GlobalID)
}
if mb != nil {
ctx = session.ContextWithTimeoutOnly(ctx, true)
@ -180,7 +180,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
XUDPManager.Lock()
delete(XUDPManager.Map, x.GlobalID)
XUDPManager.Unlock()
err = newError("XUDP new ", meta.GlobalID).Base(errors.New("failed to dispatch request to ", meta.Target).Base(err))
err = errors.New("XUDP new ", meta.GlobalID).Base(errors.New("failed to dispatch request to ", meta.Target).Base(err))
return err // it will break the whole Mux connection
}
link.Writer.WriteMultiBuffer(mb) // it's meaningless to test a new pipe
@ -188,7 +188,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
input: link.Reader,
output: link.Writer,
}
newError("XUDP new ", meta.GlobalID).Base(err).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfoInner(ctx, err, "XUDP new ", meta.GlobalID)
}
x.Mux = &Session{
input: x.Mux.input,
@ -211,7 +211,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
if meta.Option.Has(OptionData) {
buf.Copy(NewStreamReader(reader), buf.Discard)
}
return newError("failed to dispatch request.").Base(err)
return errors.New("failed to dispatch request.").Base(err)
}
s := &Session{
input: link.Reader,
@ -255,7 +255,7 @@ func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
err := buf.Copy(rr, s.output)
if err != nil && buf.IsWriteError(err) {
newError("failed to write to downstream writer. closing session ", s.ID).Base(err).WriteToLog()
errors.LogInfoInner(context.Background(), err, "failed to write to downstream writer. closing session ", s.ID)
s.Close(false)
return buf.Copy(rr, buf.Discard)
}
@ -277,7 +277,7 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
var meta FrameMetadata
err := meta.Unmarshal(reader)
if err != nil {
return newError("failed to read metadata").Base(err)
return errors.New("failed to read metadata").Base(err)
}
switch meta.SessionStatus {
@ -291,11 +291,11 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
err = w.handleStatusKeep(&meta, reader)
default:
status := meta.SessionStatus
return newError("unknown status: ", status).AtError()
return errors.New("unknown status: ", status).AtError()
}
if err != nil {
return newError("failed to process data").Base(err)
return errors.New("failed to process data").Base(err)
}
return nil
}
@ -314,7 +314,7 @@ func (w *ServerWorker) run(ctx context.Context) {
err := w.handleFrame(ctx, reader)
if err != nil {
if errors.Cause(err) != io.EOF {
newError("unexpected EOF").Base(err).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfoInner(ctx, err, "unexpected EOF")
common.Interrupt(input)
}
return

View file

@ -1,6 +1,7 @@
package mux
import (
"context"
"io"
"runtime"
"sync"
@ -8,6 +9,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/transport/pipe"
@ -180,7 +182,7 @@ func (s *Session) Close(locked bool) error {
if s.XUDP.Status == Active {
s.XUDP.Expire = time.Now().Add(time.Minute)
s.XUDP.Status = Expiring
newError("XUDP put ", s.XUDP.GlobalID).AtDebug().WriteToLog()
errors.LogDebug(context.Background(), "XUDP put ", s.XUDP.GlobalID)
}
XUDPManager.Unlock()
}
@ -230,7 +232,7 @@ func init() {
if x.Status == Expiring && now.After(x.Expire) {
x.Interrupt()
delete(XUDPManager.Map, id)
newError("XUDP del ", id).AtDebug().WriteToLog()
errors.LogDebug(context.Background(), "XUDP del ", id)
}
}
XUDPManager.Unlock()

View file

@ -2,8 +2,11 @@ package net
import (
"bytes"
"context"
"net"
"strings"
"github.com/xtls/xray-core/common/errors"
)
var (
@ -112,7 +115,7 @@ func IPAddress(ip []byte) Address {
}
return addr
default:
newError("invalid IP format: ", ip).AtError().WriteToLog()
errors.LogError(context.Background(), "invalid IP format: ", ip)
return nil
}
}

View file

@ -1,9 +0,0 @@
package net
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -3,6 +3,8 @@ package net
import (
"encoding/binary"
"strconv"
"github.com/xtls/xray-core/common/errors"
)
// Port represents a network port in TCP and UDP protocol.
@ -18,7 +20,7 @@ func PortFromBytes(port []byte) Port {
// @error when the integer is not positive or larger then 65535
func PortFromInt(val uint32) (Port, error) {
if val > 65535 {
return Port(0), newError("invalid port range: ", val)
return Port(0), errors.New("invalid port range: ", val)
}
return Port(val), nil
}
@ -28,7 +30,7 @@ func PortFromInt(val uint32) (Port, error) {
func PortFromString(s string) (Port, error) {
val, err := strconv.ParseUint(s, 10, 32)
if err != nil {
return Port(0), newError("invalid port range: ", s)
return Port(0), errors.New("invalid port range: ", s)
}
return PortFromInt(uint32(val))
}

View file

@ -1,9 +0,0 @@
package ocsp
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -8,6 +8,7 @@ import (
"net/http"
"os"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/platform/filesystem"
"golang.org/x/crypto/ocsp"
)
@ -63,26 +64,26 @@ func GetOCSPForCert(cert [][]byte) ([]byte, error) {
}
issuedCert := certificates[0]
if len(issuedCert.OCSPServer) == 0 {
return nil, newError("no OCSP server specified in cert")
return nil, errors.New("no OCSP server specified in cert")
}
if len(certificates) == 1 {
if len(issuedCert.IssuingCertificateURL) == 0 {
return nil, newError("no issuing certificate URL")
return nil, errors.New("no issuing certificate URL")
}
resp, errC := http.Get(issuedCert.IssuingCertificateURL[0])
if errC != nil {
return nil, newError("no issuing certificate URL")
return nil, errors.New("no issuing certificate URL")
}
defer resp.Body.Close()
issuerBytes, errC := io.ReadAll(resp.Body)
if errC != nil {
return nil, newError(errC)
return nil, errors.New(errC)
}
issuerCert, errC := x509.ParseCertificate(issuerBytes)
if errC != nil {
return nil, newError(errC)
return nil, errors.New(errC)
}
certificates = append(certificates, issuerCert)
@ -96,12 +97,12 @@ func GetOCSPForCert(cert [][]byte) ([]byte, error) {
reader := bytes.NewReader(ocspReq)
req, err := http.Post(issuedCert.OCSPServer[0], "application/ocsp-request", reader)
if err != nil {
return nil, newError(err)
return nil, errors.New(err)
}
defer req.Body.Close()
ocspResBytes, err := io.ReadAll(req.Body)
if err != nil {
return nil, newError(err)
return nil, errors.New(err)
}
return ocspResBytes, nil
}
@ -128,7 +129,7 @@ func parsePEMBundle(bundle []byte) ([]*x509.Certificate, error) {
}
if len(certificates) == 0 {
return nil, newError("no certificates were found while parsing the bundle")
return nil, errors.New("no certificates were found while parsing the bundle")
}
return certificates, nil

View file

@ -1,12 +1,14 @@
package ctlcmd
import (
"context"
"io"
"os"
"os/exec"
"strings"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/platform"
)
@ -15,7 +17,7 @@ import (
func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
xctl := platform.GetToolLocation("xctl")
if _, err := os.Stat(xctl); err != nil {
return nil, newError("xctl doesn't exist").Base(err)
return nil, errors.New("xctl doesn't exist").Base(err)
}
var errBuffer buf.MultiBufferContainer
@ -30,7 +32,7 @@ func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
}
if err := cmd.Start(); err != nil {
return nil, newError("failed to start xctl").Base(err)
return nil, errors.New("failed to start xctl").Base(err)
}
if err := cmd.Wait(); err != nil {
@ -38,12 +40,12 @@ func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
if errBuffer.Len() > 0 {
msg += ": \n" + strings.TrimSpace(errBuffer.MultiBuffer.String())
}
return nil, newError(msg).Base(err)
return nil, errors.New(msg).Base(err)
}
// log stderr, info message
if !errBuffer.IsEmpty() {
newError("<xctl message> \n", strings.TrimSpace(errBuffer.MultiBuffer.String())).AtInfo().WriteToLog()
errors.LogInfo(context.Background(), "<xctl message> \n", strings.TrimSpace(errBuffer.MultiBuffer.String()))
}
return outBuffer.MultiBuffer, nil

View file

@ -1,9 +0,0 @@
package ctlcmd
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -5,6 +5,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/serial"
)
@ -181,12 +182,12 @@ func (p *addressParser) readAddress(b *buf.Buffer, reader io.Reader) (net.Addres
}
if addrType >= 16 {
return nil, newError("unknown address type: ", addrType)
return nil, errors.New("unknown address type: ", addrType)
}
addrFamily := p.addrTypeMap[addrType]
if addrFamily == net.AddressFamily(afInvalid) {
return nil, newError("unknown address type: ", addrType)
return nil, errors.New("unknown address type: ", addrType)
}
switch addrFamily {
@ -216,7 +217,7 @@ func (p *addressParser) readAddress(b *buf.Buffer, reader io.Reader) (net.Addres
}
}
if !isValidDomain(domain) {
return nil, newError("invalid domain name: ", domain)
return nil, errors.New("invalid domain name: ", domain)
}
return net.DomainAddress(domain), nil
default:
@ -227,7 +228,7 @@ func (p *addressParser) readAddress(b *buf.Buffer, reader io.Reader) (net.Addres
func (p *addressParser) writeAddress(writer io.Writer, address net.Address) error {
tb := p.addrByteMap[address.Family()]
if tb == afInvalid {
return newError("unknown address family", address.Family())
return errors.New("unknown address family", address.Family())
}
switch address.Family() {
@ -241,7 +242,7 @@ func (p *addressParser) writeAddress(writer io.Writer, address net.Address) erro
case net.AddressFamilyDomain:
domain := address.Domain()
if isDomainTooLong(domain) {
return newError("Super long domain is not supported: ", domain)
return errors.New("Super long domain is not supported: ", domain)
}
if _, err := writer.Write([]byte{tb, byte(len(domain))}); err != nil {

View file

@ -1,9 +0,0 @@
package dns
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -6,6 +6,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/serial"
"golang.org/x/net/dns/dnsmessage"
)
@ -96,7 +97,7 @@ func (r *TCPReader) ReadMessage() (*buf.Buffer, error) {
return nil, err
}
if size > buf.Size {
return nil, newError("message size too large: ", size)
return nil, errors.New("message size too large: ", size)
}
b := buf.New()
if _, err := b.ReadFullFrom(r.reader, int32(size)); err != nil {

View file

@ -1,9 +0,0 @@
package protocol
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -13,6 +13,7 @@ import (
"time"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
)
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
@ -27,11 +28,11 @@ type Certificate struct {
func ParseCertificate(certPEM []byte, keyPEM []byte) (*Certificate, error) {
certBlock, _ := pem.Decode(certPEM)
if certBlock == nil {
return nil, newError("failed to decode certificate")
return nil, errors.New("failed to decode certificate")
}
keyBlock, _ := pem.Decode(keyPEM)
if keyBlock == nil {
return nil, newError("failed to decode key")
return nil, errors.New("failed to decode key")
}
return &Certificate{
Certificate: certBlock.Bytes,
@ -116,7 +117,7 @@ func Generate(parent *Certificate, opts ...Option) (*Certificate, error) {
// higher signing performance than RSA2048
selfKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, newError("failed to generate self private key").Base(err)
return nil, errors.New("failed to generate self private key").Base(err)
}
parentKey = selfKey
if parent != nil {
@ -128,7 +129,7 @@ func Generate(parent *Certificate, opts ...Option) (*Certificate, error) {
pKey, err = x509.ParsePKCS1PrivateKey(parent.PrivateKey)
}
if err != nil {
return nil, newError("failed to parse parent private key").Base(err)
return nil, errors.New("failed to parse parent private key").Base(err)
}
parentKey = pKey
}
@ -136,7 +137,7 @@ func Generate(parent *Certificate, opts ...Option) (*Certificate, error) {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, newError("failed to generate serial number").Base(err)
return nil, errors.New("failed to generate serial number").Base(err)
}
template := &x509.Certificate{
@ -156,19 +157,19 @@ func Generate(parent *Certificate, opts ...Option) (*Certificate, error) {
if parent != nil {
pCert, err := x509.ParseCertificate(parent.Certificate)
if err != nil {
return nil, newError("failed to parse parent certificate").Base(err)
return nil, errors.New("failed to parse parent certificate").Base(err)
}
parentCert = pCert
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, parentCert, publicKey(selfKey), parentKey)
if err != nil {
return nil, newError("failed to create certificate").Base(err)
return nil, errors.New("failed to create certificate").Base(err)
}
privateKey, err := x509.MarshalPKCS8PrivateKey(selfKey)
if err != nil {
return nil, newError("Unable to marshal private key").Base(err)
return nil, errors.New("Unable to marshal private key").Base(err)
}
return &Certificate{

View file

@ -10,6 +10,7 @@ import (
"time"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/task"
)
@ -41,7 +42,7 @@ func generate(domainNames []string, isCA bool, jsonOutput bool, fileOutput strin
cert, err := Generate(nil, opts...)
if err != nil {
return newError("failed to generate TLS certificate").Base(err)
return errors.New("failed to generate TLS certificate").Base(err)
}
if jsonOutput {

View file

@ -1,9 +0,0 @@
package cert
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -1,8 +1,10 @@
package protocol
import "github.com/xtls/xray-core/common/errors"
func (u *User) GetTypedAccount() (Account, error) {
if u.GetAccount() == nil {
return nil, newError("Account missing").AtWarning()
return nil, errors.New("Account missing").AtWarning()
}
rawAccount, err := u.Account.GetInstance()
@ -15,7 +17,7 @@ func (u *User) GetTypedAccount() (Account, error) {
if account, ok := rawAccount.(Account); ok {
return account, nil
}
return nil, newError("Unknown account type: ", u.Account.Type)
return nil, errors.New("Unknown account type: ", u.Account.Type)
}
func (u *User) ToMemoryUser() (*MemoryUser, error) {

View file

@ -1,9 +0,0 @@
package retry
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -4,9 +4,11 @@ package retry // import "github.com/xtls/xray-core/common/retry"
import (
"time"
"github.com/xtls/xray-core/common/errors"
)
var ErrRetryFailed = newError("all retry attempts failed")
var ErrRetryFailed = errors.New("all retry attempts failed")
// Strategy is a way to retry on a specific function.
type Strategy interface {
@ -36,7 +38,7 @@ func (r *retryer) On(method func() error) error {
time.Sleep(time.Duration(delay) * time.Millisecond)
attempt++
}
return newError(accumulatedError).Base(ErrRetryFailed)
return errors.New(accumulatedError).Base(ErrRetryFailed)
}
// Timed returns a retry strategy with fixed interval.

View file

@ -4,6 +4,7 @@ import (
"context"
_ "unsafe"
"github.com/xtls/xray-core/common/ctx"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/routing"
)
@ -11,35 +12,19 @@ import (
//go:linkname IndependentCancelCtx context.newCancelCtx
func IndependentCancelCtx(parent context.Context) context.Context
type sessionKey int
const (
idSessionKey sessionKey = iota
inboundSessionKey
outboundSessionKey
contentSessionKey
muxPreferedSessionKey
sockoptSessionKey
trackedConnectionErrorKey
dispatcherKey
timeoutOnlyKey
allowedNetworkKey
handlerSessionKey
inboundSessionKey ctx.SessionKey = 1
outboundSessionKey ctx.SessionKey = 2
contentSessionKey ctx.SessionKey = 3
muxPreferedSessionKey ctx.SessionKey = 4
sockoptSessionKey ctx.SessionKey = 5
trackedConnectionErrorKey ctx.SessionKey = 6
dispatcherKey ctx.SessionKey = 7
timeoutOnlyKey ctx.SessionKey = 8
allowedNetworkKey ctx.SessionKey = 9
handlerSessionKey ctx.SessionKey = 10
)
// ContextWithID returns a new context with the given ID.
func ContextWithID(ctx context.Context, id ID) context.Context {
return context.WithValue(ctx, idSessionKey, id)
}
// IDFromContext returns ID in this context, or 0 if not contained.
func IDFromContext(ctx context.Context) ID {
if id, ok := ctx.Value(idSessionKey).(ID); ok {
return id
}
return 0
}
func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
return context.WithValue(ctx, inboundSessionKey, inbound)
}

View file

@ -5,20 +5,18 @@ import (
"context"
"math/rand"
c "github.com/xtls/xray-core/common/ctx"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/signal"
)
// ID of a session.
type ID uint32
// NewID generates a new ID. The generated ID is high likely to be unique, but not cryptographically secure.
// The generated ID will never be 0.
func NewID() ID {
func NewID() c.ID {
for {
id := ID(rand.Uint32())
id := c.ID(rand.Uint32())
if id != 0 {
return id
}
@ -28,7 +26,7 @@ func NewID() ID {
// ExportIDToError transfers session.ID into an error object, for logging purpose.
// This can be used with error.WriteToLog().
func ExportIDToError(ctx context.Context) errors.ExportOption {
id := IDFromContext(ctx)
id := c.IDFromContext(ctx)
return func(h *errors.ExportOptionHolder) {
h.SessionID = uint32(id)
}

View file

@ -9,7 +9,6 @@ import (
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport"
)
@ -47,5 +46,5 @@ func (d *Dispatcher) NewPacketConnection(ctx context.Context, conn N.PacketConn,
}
func (d *Dispatcher) NewError(ctx context.Context, err error) {
d.newErrorFunc(err).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, err.Error())
}

View file

@ -5,7 +5,6 @@ import (
"github.com/sagernet/sing/common/logger"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/session"
)
var _ logger.ContextLogger = (*XrayLogger)(nil)
@ -24,19 +23,19 @@ func (l *XrayLogger) Trace(args ...any) {
}
func (l *XrayLogger) Debug(args ...any) {
l.newError(args...).AtDebug().WriteToLog()
errors.LogDebug(context.Background(), args...)
}
func (l *XrayLogger) Info(args ...any) {
l.newError(args...).AtInfo().WriteToLog()
errors.LogInfo(context.Background(), args...)
}
func (l *XrayLogger) Warn(args ...any) {
l.newError(args...).AtWarning().WriteToLog()
errors.LogWarning(context.Background(), args...)
}
func (l *XrayLogger) Error(args ...any) {
l.newError(args...).AtError().WriteToLog()
errors.LogError(context.Background(), args...)
}
func (l *XrayLogger) Fatal(args ...any) {
@ -49,19 +48,19 @@ func (l *XrayLogger) TraceContext(ctx context.Context, args ...any) {
}
func (l *XrayLogger) DebugContext(ctx context.Context, args ...any) {
l.newError(args...).AtDebug().WriteToLog(session.ExportIDToError(ctx))
errors.LogDebug(ctx, args...)
}
func (l *XrayLogger) InfoContext(ctx context.Context, args ...any) {
l.newError(args...).AtInfo().WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, args...)
}
func (l *XrayLogger) WarnContext(ctx context.Context, args ...any) {
l.newError(args...).AtWarning().WriteToLog(session.ExportIDToError(ctx))
errors.LogWarning(ctx, args...)
}
func (l *XrayLogger) ErrorContext(ctx context.Context, args ...any) {
l.newError(args...).AtError().WriteToLog(session.ExportIDToError(ctx))
errors.LogError(ctx, args...)
}
func (l *XrayLogger) FatalContext(ctx context.Context, args ...any) {

View file

@ -3,6 +3,8 @@ package common
import (
"context"
"reflect"
"github.com/xtls/xray-core/common/errors"
)
// ConfigCreator is a function to create an object by a config.
@ -14,7 +16,7 @@ var typeCreatorRegistry = make(map[reflect.Type]ConfigCreator)
func RegisterConfig(config interface{}, configCreator ConfigCreator) error {
configType := reflect.TypeOf(config)
if _, found := typeCreatorRegistry[configType]; found {
return newError(configType.Name() + " is already registered").AtError()
return errors.New(configType.Name() + " is already registered").AtError()
}
typeCreatorRegistry[configType] = configCreator
return nil
@ -25,7 +27,7 @@ func CreateObject(ctx context.Context, config interface{}) (interface{}, error)
configType := reflect.TypeOf(config)
creator, found := typeCreatorRegistry[configType]
if !found {
return nil, newError(configType.String() + " is not registered").AtError()
return nil, errors.New(configType.String() + " is not registered").AtError()
}
return creator(ctx, config)
}

View file

@ -1,9 +0,0 @@
package xudp
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -11,6 +11,7 @@ import (
"time"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/protocol"
@ -36,7 +37,7 @@ func init() {
}
rand.Read(BaseKey)
go func() {
time.Sleep(100 * time.Millisecond) // this is not nice, but need to give some time for Android to setup ENV
time.Sleep(100 * time.Millisecond) // this is not nice, but need to give some time for Android to setup ENV
if raw := platform.NewEnvFlag(platform.XUDPBaseKey).GetValue(func() string { return "" }); raw != "" {
if BaseKey, _ = base64.RawURLEncoding.DecodeString(raw); len(BaseKey) == 32 {
return
@ -56,7 +57,7 @@ func GetGlobalID(ctx context.Context) (globalID [8]byte) {
h.Write([]byte(inbound.Source.String()))
copy(globalID[:], h.Sum(nil))
if Show {
newError(fmt.Sprintf("XUDP inbound.Source.String(): %v\tglobalID: %v\n", inbound.Source.String(), globalID)).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, fmt.Sprintf("XUDP inbound.Source.String(): %v\tglobalID: %v\n", inbound.Source.String(), globalID))
}
}
return