Browse Source

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
pull/3485/head
yuhan6665 5 months ago committed by GitHub
parent
commit
079d0bd8a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 11
      app/commander/commander.go
  2. 9
      app/commander/errors.generated.go
  3. 3
      app/commander/outbound.go
  4. 25
      app/dispatcher/default.go
  5. 9
      app/dispatcher/errors.generated.go
  6. 9
      app/dispatcher/fakednssniffer.go
  7. 3
      app/dispatcher/sniffer.go
  8. 7
      app/dns/config.go
  9. 28
      app/dns/dns.go
  10. 12
      app/dns/dnscommon.go
  11. 9
      app/dns/errors.generated.go
  12. 9
      app/dns/fakedns/errors.generated.go
  13. 17
      app/dns/fakedns/fake.go
  14. 13
      app/dns/hosts.go
  15. 22
      app/dns/nameserver.go
  16. 25
      app/dns/nameserver_doh.go
  17. 7
      app/dns/nameserver_fakedns.go
  18. 7
      app/dns/nameserver_local.go
  19. 29
      app/dns/nameserver_quic.go
  20. 27
      app/dns/nameserver_tcp.go
  21. 22
      app/dns/nameserver_udp.go
  22. 7
      app/log/command/command.go
  23. 9
      app/log/command/errors.generated.go
  24. 9
      app/log/errors.generated.go
  25. 9
      app/log/log.go
  26. 5
      app/log/log_creator.go
  27. 9
      app/metrics/errors.generated.go
  28. 5
      app/metrics/metrics.go
  29. 3
      app/metrics/outbound.go
  30. 12
      app/observatory/burst/burstobserver.go
  31. 9
      app/observatory/burst/errors.generated.go
  32. 17
      app/observatory/burst/healthping.go
  33. 9
      app/observatory/errors.generated.go
  34. 6
      app/observatory/explainErrors.go
  35. 25
      app/observatory/observer.go
  36. 9
      app/policy/errors.generated.go
  37. 19
      app/proxyman/command/command.go
  38. 9
      app/proxyman/command/errors.generated.go
  39. 10
      app/proxyman/inbound/always.go
  40. 11
      app/proxyman/inbound/dynamic.go
  41. 9
      app/proxyman/inbound/errors.generated.go
  42. 21
      app/proxyman/inbound/inbound.go
  43. 56
      app/proxyman/inbound/worker.go
  44. 9
      app/proxyman/outbound/errors.generated.go
  45. 43
      app/proxyman/outbound/handler.go
  46. 2
      app/proxyman/outbound/outbound.go
  47. 5
      app/proxyman/outbound/uot.go
  48. 9
      app/reverse/bridge.go
  49. 9
      app/reverse/errors.generated.go
  50. 25
      app/reverse/portal.go
  51. 23
      app/router/balancing.go
  52. 4
      app/router/balancing_override.go
  53. 17
      app/router/command/command.go
  54. 9
      app/router/command/errors.generated.go
  55. 7
      app/router/condition.go
  56. 14
      app/router/config.go
  57. 9
      app/router/errors.generated.go
  58. 13
      app/router/router.go
  59. 7
      app/router/strategy_leastload.go
  60. 3
      app/router/strategy_leastping.go
  61. 7
      app/router/weight.go
  62. 3
      app/stats/channel.go
  63. 5
      app/stats/command/command.go
  64. 9
      app/stats/command/errors.generated.go
  65. 9
      app/stats/errors.generated.go
  66. 14
      app/stats/stats.go
  67. 5
      common/buf/buffer.go
  68. 2
      common/buf/copy.go
  69. 4
      common/buf/copy_test.go
  70. 9
      common/buf/errors.generated.go
  71. 6
      common/buf/io.go
  72. 2
      common/buf/reader.go
  73. 9
      common/crypto/auth.go
  74. 9
      common/crypto/errors.generated.go
  75. 25
      common/ctx/context.go
  76. 7
      common/drain/drainer.go
  77. 9
      common/drain/errors.generated.go
  78. 9
      common/errors.generated.go
  79. 37
      common/errors/errorgen/main.go
  80. 115
      common/errors/errors.go
  81. 10
      common/errors/errors_test.go
  82. 22
      common/mux/client.go
  83. 9
      common/mux/errors.generated.go
  84. 11
      common/mux/frame.go
  85. 3
      common/mux/reader.go
  86. 26
      common/mux/server.go
  87. 6
      common/mux/session.go
  88. 5
      common/net/address.go
  89. 9
      common/net/errors.generated.go
  90. 6
      common/net/port.go
  91. 9
      common/ocsp/errors.generated.go
  92. 17
      common/ocsp/ocsp.go
  93. 10
      common/platform/ctlcmd/ctlcmd.go
  94. 9
      common/platform/ctlcmd/errors.generated.go
  95. 11
      common/protocol/address.go
  96. 9
      common/protocol/dns/errors.generated.go
  97. 3
      common/protocol/dns/io.go
  98. 9
      common/protocol/errors.generated.go
  99. 17
      common/protocol/tls/cert/cert.go
  100. 3
      common/protocol/tls/cert/cert_test.go
  101. Some files were not shown because too many files have changed in this diff Show More

11
app/commander/commander.go

@ -8,6 +8,7 @@ import (
"sync" "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
core "github.com/xtls/xray-core/core" core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
@ -46,7 +47,7 @@ func NewCommander(ctx context.Context, config *Config) (*Commander, error) {
} }
service, ok := rawService.(Service) service, ok := rawService.(Service)
if !ok { if !ok {
return nil, newError("not a Service.") return nil, errors.New("not a Service.")
} }
c.services = append(c.services, service) c.services = append(c.services, service)
} }
@ -70,16 +71,16 @@ func (c *Commander) Start() error {
var listen = func(listener net.Listener) { var listen = func(listener net.Listener) {
if err := c.server.Serve(listener); err != nil { if err := c.server.Serve(listener); err != nil {
newError("failed to start grpc server").Base(err).AtError().WriteToLog() errors.LogErrorInner(context.Background(), err, "failed to start grpc server")
} }
} }
if len(c.listen) > 0 { if len(c.listen) > 0 {
if l, err := net.Listen("tcp", c.listen); err != nil { if l, err := net.Listen("tcp", c.listen); err != nil {
newError("API server failed to listen on ", c.listen).Base(err).AtError().WriteToLog() errors.LogErrorInner(context.Background(), err, "API server failed to listen on ", c.listen)
return err return err
} else { } else {
newError("API server listening on ", l.Addr()).AtInfo().WriteToLog() errors.LogInfo(context.Background(), "API server listening on ", l.Addr())
go listen(l) go listen(l)
} }
return nil return nil
@ -93,7 +94,7 @@ func (c *Commander) Start() error {
go listen(listener) go listen(listener)
if err := c.ohm.RemoveHandler(context.Background(), c.tag); err != nil { if err := c.ohm.RemoveHandler(context.Background(), c.tag); err != nil {
newError("failed to remove existing handler").WriteToLog() errors.LogInfoInner(context.Background(), err, "failed to remove existing handler")
} }
return c.ohm.AddHandler(context.Background(), &Outbound{ return c.ohm.AddHandler(context.Background(), &Outbound{

9
app/commander/errors.generated.go

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

3
app/commander/outbound.go

@ -5,6 +5,7 @@ import (
"sync" "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
@ -31,7 +32,7 @@ func (l *OutboundListener) add(conn net.Conn) {
func (l *OutboundListener) Accept() (net.Conn, error) { func (l *OutboundListener) Accept() (net.Conn, error) {
select { select {
case <-l.done.Wait(): case <-l.done.Wait():
return nil, newError("listen closed") return nil, errors.New("listen closed")
case c := <-l.buffer: case c := <-l.buffer:
return c, nil return c, nil
} }

25
app/dispatcher/default.go

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@ -26,7 +27,7 @@ import (
"github.com/xtls/xray-core/transport/pipe" "github.com/xtls/xray-core/transport/pipe"
) )
var errSniffingTimeout = newError("timeout on sniffing") var errSniffingTimeout = errors.New("timeout on sniffing")
type cachedReader struct { type cachedReader struct {
sync.Mutex sync.Mutex
@ -191,7 +192,7 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
pattern := d[7:] pattern := d[7:]
re, err := regexp.Compile(pattern) re, err := regexp.Compile(pattern)
if err != nil { if err != nil {
newError("Unable to compile regex").WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "Unable to compile regex")
continue continue
} }
if re.MatchString(domain) { if re.MatchString(domain) {
@ -213,7 +214,7 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
} }
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" && if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" &&
fkr0.IsIPInIPPool(destination.Address) { fkr0.IsIPInIPPool(destination.Address) {
newError("Using sniffer ", protocolString, " since the fake DNS missed").WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "Using sniffer ", protocolString, " since the fake DNS missed")
return true return true
} }
if resultSubset, ok := result.(SnifferIsProtoSubsetOf); ok { if resultSubset, ok := result.(SnifferIsProtoSubsetOf); ok {
@ -261,7 +262,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
} }
if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) { if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
domain := result.Domain() domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "sniffed domain: ", domain)
destination.Address = net.ParseAddress(domain) destination.Address = net.ParseAddress(domain)
protocol := result.Protocol() protocol := result.Protocol()
if resComp, ok := result.(SnifferResultComposite); ok { if resComp, ok := result.(SnifferResultComposite); ok {
@ -286,7 +287,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
// DispatchLink implements routing.Dispatcher. // DispatchLink implements routing.Dispatcher.
func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.Destination, outbound *transport.Link) error { func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.Destination, outbound *transport.Link) error {
if !destination.IsValid() { if !destination.IsValid() {
return newError("Dispatcher: Invalid destination.") return errors.New("Dispatcher: Invalid destination.")
} }
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
if len(outbounds) == 0 { if len(outbounds) == 0 {
@ -315,7 +316,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
} }
if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) { if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
domain := result.Domain() domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "sniffed domain: ", domain)
destination.Address = net.ParseAddress(domain) destination.Address = net.ParseAddress(domain)
protocol := result.Protocol() protocol := result.Protocol()
if resComp, ok := result.(SnifferResultComposite); ok { if resComp, ok := result.(SnifferResultComposite); ok {
@ -407,10 +408,10 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
ctx = session.SetForcedOutboundTagToContext(ctx, "") ctx = session.SetForcedOutboundTagToContext(ctx, "")
if h := d.ohm.GetHandler(forcedOutboundTag); h != nil { if h := d.ohm.GetHandler(forcedOutboundTag); h != nil {
isPickRoute = 1 isPickRoute = 1
newError("taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]")
handler = h handler = h
} else { } else {
newError("non existing tag for platform initialized detour: ", forcedOutboundTag).AtError().WriteToLog(session.ExportIDToError(ctx)) errors.LogError(ctx, "non existing tag for platform initialized detour: ", forcedOutboundTag)
common.Close(link.Writer) common.Close(link.Writer)
common.Interrupt(link.Reader) common.Interrupt(link.Reader)
return return
@ -420,13 +421,13 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
outTag := route.GetOutboundTag() outTag := route.GetOutboundTag()
if h := d.ohm.GetHandler(outTag); h != nil { if h := d.ohm.GetHandler(outTag); h != nil {
isPickRoute = 2 isPickRoute = 2
newError("taking detour [", outTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "taking detour [", outTag, "] for [", destination, "]")
handler = h handler = h
} else { } else {
newError("non existing outTag: ", outTag).AtWarning().WriteToLog(session.ExportIDToError(ctx)) errors.LogWarning(ctx, "non existing outTag: ", outTag)
} }
} else { } else {
newError("default route for ", destination).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "default route for ", destination)
} }
} }
@ -435,7 +436,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
} }
if handler == nil { if handler == nil {
newError("default outbound handler not exist").WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "default outbound handler not exist")
common.Close(link.Writer) common.Close(link.Writer)
common.Interrupt(link.Reader) common.Interrupt(link.Reader)
return return

9
app/dispatcher/errors.generated.go

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

9
app/dispatcher/fakednssniffer.go

@ -5,6 +5,7 @@ import (
"strings" "strings"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
@ -22,7 +23,7 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
} }
if fakeDNSEngine == nil { if fakeDNSEngine == nil {
errNotInit := newError("FakeDNSEngine is not initialized, but such a sniffer is used").AtError() errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
return protocolSnifferWithMetadata{}, errNotInit return protocolSnifferWithMetadata{}, errNotInit
} }
return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) { return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
@ -31,7 +32,7 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP { if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP {
domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address) domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address)
if domainFromFakeDNS != "" { if domainFromFakeDNS != "" {
newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String()).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, "fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String())
return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil
} }
} }
@ -109,10 +110,10 @@ func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWit
} }
return nil, common.ErrNoClue return nil, common.ErrNoClue
} }
newError("ip address not in fake dns range, return as is").AtDebug().WriteToLog() errors.LogDebug(ctx, "ip address not in fake dns range, return as is")
return nil, common.ErrNoClue return nil, common.ErrNoClue
} }
newError("fake dns sniffer did not set address in range option, assume false.").AtWarning().WriteToLog() errors.LogWarning(ctx, "fake dns sniffer did not set address in range option, assume false.")
return nil, common.ErrNoClue return nil, common.ErrNoClue
}, },
metadataSniffer: false, metadataSniffer: false,

3
app/dispatcher/sniffer.go

@ -4,6 +4,7 @@ import (
"context" "context"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol/bittorrent" "github.com/xtls/xray-core/common/protocol/bittorrent"
"github.com/xtls/xray-core/common/protocol/http" "github.com/xtls/xray-core/common/protocol/http"
@ -52,7 +53,7 @@ func NewSniffer(ctx context.Context) *Sniffer {
return ret return ret
} }
var errUnknownContent = newError("unknown content") var errUnknownContent = errors.New("unknown content")
func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) { func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
var pendingSniffer []protocolSnifferWithMetadata var pendingSniffer []protocolSnifferWithMetadata

7
app/dns/config.go

@ -1,6 +1,7 @@
package dns package dns
import ( import (
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/strmatcher" "github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/common/uuid" "github.com/xtls/xray-core/common/uuid"
@ -36,11 +37,11 @@ var localTLDsAndDotlessDomainsRule = &NameServer_OriginalRule{
func toStrMatcher(t DomainMatchingType, domain string) (strmatcher.Matcher, error) { func toStrMatcher(t DomainMatchingType, domain string) (strmatcher.Matcher, error) {
strMType, f := typeMap[t] strMType, f := typeMap[t]
if !f { if !f {
return nil, newError("unknown mapping type", t).AtWarning() return nil, errors.New("unknown mapping type", t).AtWarning()
} }
matcher, err := strMType.New(domain) matcher, err := strMType.New(domain)
if err != nil { if err != nil {
return nil, newError("failed to create str matcher").Base(err) return nil, errors.New("failed to create str matcher").Base(err)
} }
return matcher, nil return matcher, nil
} }
@ -51,7 +52,7 @@ func toNetIP(addrs []net.Address) ([]net.IP, error) {
if addr.Family().IsIP() { if addr.Family().IsIP() {
ips = append(ips, addr.IP()) ips = append(ips, addr.IP())
} else { } else {
return nil, newError("Failed to convert address", addr, "to Net IP.").AtWarning() return nil, errors.New("Failed to convert address", addr, "to Net IP.").AtWarning()
} }
} }
return ips, nil return ips, nil

28
app/dns/dns.go

@ -54,7 +54,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
case 0, net.IPv4len, net.IPv6len: case 0, net.IPv4len, net.IPv6len:
clientIP = net.IP(config.ClientIp) clientIP = net.IP(config.ClientIp)
default: default:
return nil, newError("unexpected client IP length ", len(config.ClientIp)) return nil, errors.New("unexpected client IP length ", len(config.ClientIp))
} }
var ipOption *dns.IPOption var ipOption *dns.IPOption
@ -81,7 +81,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
hosts, err := NewStaticHosts(config.StaticHosts, config.Hosts) hosts, err := NewStaticHosts(config.StaticHosts, config.Hosts)
if err != nil { if err != nil {
return nil, newError("failed to create hosts").Base(err) return nil, errors.New("failed to create hosts").Base(err)
} }
clients := []*Client{} clients := []*Client{}
@ -99,7 +99,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
features.PrintDeprecatedFeatureWarning("simple DNS server") features.PrintDeprecatedFeatureWarning("simple DNS server")
client, err := NewSimpleClient(ctx, endpoint, clientIP) client, err := NewSimpleClient(ctx, endpoint, clientIP)
if err != nil { if err != nil {
return nil, newError("failed to create client").Base(err) return nil, errors.New("failed to create client").Base(err)
} }
clients = append(clients, client) clients = append(clients, client)
} }
@ -122,7 +122,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
} }
client, err := NewClient(ctx, ns, myClientIP, geoipContainer, &matcherInfos, updateDomain) client, err := NewClient(ctx, ns, myClientIP, geoipContainer, &matcherInfos, updateDomain)
if err != nil { if err != nil {
return nil, newError("failed to create client").Base(err) return nil, errors.New("failed to create client").Base(err)
} }
clients = append(clients, client) clients = append(clients, client)
} }
@ -170,7 +170,7 @@ func (s *DNS) IsOwnLink(ctx context.Context) bool {
// LookupIP implements dns.Client. // LookupIP implements dns.Client.
func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) { func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
if domain == "" { if domain == "" {
return nil, newError("empty domain name") return nil, errors.New("empty domain name")
} }
option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable
@ -190,10 +190,10 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled) case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
return nil, dns.ErrEmptyResponse return nil, dns.ErrEmptyResponse
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement
newError("domain replaced: ", domain, " -> ", addrs[0].Domain()).WriteToLog() errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].Domain())
domain = addrs[0].Domain() domain = addrs[0].Domain()
default: // Successfully found ip records in static host default: // Successfully found ip records in static host
newError("returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs).WriteToLog() errors.LogInfo(s.ctx, "returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs)
return toNetIP(addrs) return toNetIP(addrs)
} }
@ -202,7 +202,7 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag}) ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag})
for _, client := range s.sortClients(domain) { for _, client := range s.sortClients(domain) {
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") { if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
newError("skip DNS resolution for domain ", domain, " at server ", client.Name()).AtDebug().WriteToLog() errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
continue continue
} }
ips, err := client.QueryIP(ctx, domain, option, s.disableCache) ips, err := client.QueryIP(ctx, domain, option, s.disableCache)
@ -210,7 +210,7 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
return ips, nil return ips, nil
} }
if err != nil { if err != nil {
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog() errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name())
errs = append(errs, err) errs = append(errs, err)
} }
// 5 for RcodeRefused in miekg/dns, hardcode to reduce binary size // 5 for RcodeRefused in miekg/dns, hardcode to reduce binary size
@ -219,7 +219,7 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
} }
} }
return nil, newError("returning nil for domain ", domain).Base(errors.Combine(errs...)) return nil, errors.New("returning nil for domain ", domain).Base(errors.Combine(errs...))
} }
// LookupHosts implements dns.HostsLookup. // LookupHosts implements dns.HostsLookup.
@ -231,7 +231,7 @@ func (s *DNS) LookupHosts(domain string) *net.Address {
// Normalize the FQDN form query // Normalize the FQDN form query
addrs := s.hosts.Lookup(domain, *s.ipOption) addrs := s.hosts.Lookup(domain, *s.ipOption)
if len(addrs) > 0 { if len(addrs) > 0 {
newError("domain replaced: ", domain, " -> ", addrs[0].String()).AtInfo().WriteToLog() errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].String())
return &addrs[0] return &addrs[0]
} }
@ -289,16 +289,16 @@ func (s *DNS) sortClients(domain string) []*Client {
} }
if len(domainRules) > 0 { if len(domainRules) > 0 {
newError("domain ", domain, " matches following rules: ", domainRules).AtDebug().WriteToLog() errors.LogDebug(s.ctx, "domain ", domain, " matches following rules: ", domainRules)
} }
if len(clientNames) > 0 { if len(clientNames) > 0 {
newError("domain ", domain, " will use DNS in order: ", clientNames).AtDebug().WriteToLog() errors.LogDebug(s.ctx, "domain ", domain, " will use DNS in order: ", clientNames)
} }
if len(clients) == 0 { if len(clients) == 0 {
clients = append(clients, s.clients[0]) clients = append(clients, s.clients[0])
clientNames = append(clientNames, s.clients[0].Name()) clientNames = append(clientNames, s.clients[0].Name())
newError("domain ", domain, " will use the first DNS: ", clientNames).AtDebug().WriteToLog() errors.LogDebug(s.ctx, "domain ", domain, " will use the first DNS: ", clientNames)
} }
return clients return clients

12
app/dns/dnscommon.go

@ -171,10 +171,10 @@ func parseResponse(payload []byte) (*IPRecord, error) {
var parser dnsmessage.Parser var parser dnsmessage.Parser
h, err := parser.Start(payload) h, err := parser.Start(payload)
if err != nil { if err != nil {
return nil, newError("failed to parse DNS response").Base(err).AtWarning() return nil, errors.New("failed to parse DNS response").Base(err).AtWarning()
} }
if err := parser.SkipAllQuestions(); err != nil { if err := parser.SkipAllQuestions(); err != nil {
return nil, newError("failed to skip questions in DNS response").Base(err).AtWarning() return nil, errors.New("failed to skip questions in DNS response").Base(err).AtWarning()
} }
now := time.Now() now := time.Now()
@ -189,7 +189,7 @@ L:
ah, err := parser.AnswerHeader() ah, err := parser.AnswerHeader()
if err != nil { if err != nil {
if err != dnsmessage.ErrSectionDone { if err != dnsmessage.ErrSectionDone {
newError("failed to parse answer section for domain: ", ah.Name.String()).Base(err).WriteToLog() errors.LogInfoInner(context.Background(), err, "failed to parse answer section for domain: ", ah.Name.String())
} }
break break
} }
@ -207,20 +207,20 @@ L:
case dnsmessage.TypeA: case dnsmessage.TypeA:
ans, err := parser.AResource() ans, err := parser.AResource()
if err != nil { if err != nil {
newError("failed to parse A record for domain: ", ah.Name).Base(err).WriteToLog() errors.LogInfoInner(context.Background(), err, "failed to parse A record for domain: ", ah.Name)
break L break L
} }
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:])) ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:]))
case dnsmessage.TypeAAAA: case dnsmessage.TypeAAAA:
ans, err := parser.AAAAResource() ans, err := parser.AAAAResource()
if err != nil { if err != nil {
newError("failed to parse AAAA record for domain: ", ah.Name).Base(err).WriteToLog() errors.LogInfoInner(context.Background(), err, "failed to parse AAAA record for domain: ", ah.Name)
break L break L
} }
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.AAAA[:])) ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.AAAA[:]))
default: default:
if err := parser.SkipAnswer(); err != nil { if err := parser.SkipAnswer(); err != nil {
newError("failed to skip answer").Base(err).WriteToLog() errors.LogInfoInner(context.Background(), err, "failed to skip answer")
break L break L
} }
continue continue

9
app/dns/errors.generated.go

@ -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{})
}

9
app/dns/fakedns/errors.generated.go

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

17
app/dns/fakedns/fake.go

@ -10,6 +10,7 @@ import (
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/cache" "github.com/xtls/xray-core/common/cache"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
@ -45,7 +46,7 @@ func (fkdns *Holder) Start() error {
if fkdns.config != nil && fkdns.config.IpPool != "" && fkdns.config.LruSize != 0 { if fkdns.config != nil && fkdns.config.IpPool != "" && fkdns.config.LruSize != 0 {
return fkdns.initializeFromConfig() return fkdns.initializeFromConfig()
} }
return newError("invalid fakeDNS setting") return errors.New("invalid fakeDNS setting")
} }
func (fkdns *Holder) Close() error { func (fkdns *Holder) Close() error {
@ -60,7 +61,7 @@ func NewFakeDNSHolder() (*Holder, error) {
var err error var err error
if fkdns, err = NewFakeDNSHolderConfigOnly(nil); err != nil { if fkdns, err = NewFakeDNSHolderConfigOnly(nil); err != nil {
return nil, newError("Unable to create Fake Dns Engine").Base(err).AtError() return nil, errors.New("Unable to create Fake Dns Engine").Base(err).AtError()
} }
err = fkdns.initialize(dns.FakeIPv4Pool, 65535) err = fkdns.initialize(dns.FakeIPv4Pool, 65535)
if err != nil { if err != nil {
@ -82,13 +83,13 @@ func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
var err error var err error
if _, ipRange, err = gonet.ParseCIDR(ipPoolCidr); err != nil { if _, ipRange, err = gonet.ParseCIDR(ipPoolCidr); err != nil {
return newError("Unable to parse CIDR for Fake DNS IP assignment").Base(err).AtError() return errors.New("Unable to parse CIDR for Fake DNS IP assignment").Base(err).AtError()
} }
ones, bits := ipRange.Mask.Size() ones, bits := ipRange.Mask.Size()
rooms := bits - ones rooms := bits - ones
if math.Log2(float64(lruSize)) >= float64(rooms) { if math.Log2(float64(lruSize)) >= float64(rooms) {
return newError("LRU size is bigger than subnet size").AtError() return errors.New("LRU size is bigger than subnet size").AtError()
} }
fkdns.domainToIP = cache.NewLru(lruSize) fkdns.domainToIP = cache.NewLru(lruSize)
fkdns.ipRange = ipRange fkdns.ipRange = ipRange
@ -137,7 +138,7 @@ func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string {
if k, ok := fkdns.domainToIP.GetKeyFromValue(ip); ok { if k, ok := fkdns.domainToIP.GetKeyFromValue(ip); ok {
return k.(string) return k.(string)
} }
newError("A fake ip request to ", ip, ", however there is no matching domain name in fake DNS").AtInfo().WriteToLog() errors.LogInfo(context.Background(), "A fake ip request to ", ip, ", however there is no matching domain name in fake DNS")
return "" return ""
} }
@ -192,10 +193,10 @@ func (h *HolderMulti) Start() error {
for _, v := range h.holders { for _, v := range h.holders {
if v.config != nil && v.config.IpPool != "" && v.config.LruSize != 0 { if v.config != nil && v.config.IpPool != "" && v.config.LruSize != 0 {
if err := v.Start(); err != nil { if err := v.Start(); err != nil {
return newError("Cannot start all fake dns pools").Base(err) return errors.New("Cannot start all fake dns pools").Base(err)
} }
} else { } else {
return newError("invalid fakeDNS setting") return errors.New("invalid fakeDNS setting")
} }
} }
return nil return nil
@ -204,7 +205,7 @@ func (h *HolderMulti) Start() error {
func (h *HolderMulti) Close() error { func (h *HolderMulti) Close() error {
for _, v := range h.holders { for _, v := range h.holders {
if err := v.Close(); err != nil { if err := v.Close(); err != nil {
return newError("Cannot close all fake dns pools").Base(err) return errors.New("Cannot close all fake dns pools").Base(err)
} }
} }
return nil return nil

13
app/dns/hosts.go

@ -1,7 +1,10 @@
package dns package dns
import ( import (
"context"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/strmatcher" "github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/features" "github.com/xtls/xray-core/features"
@ -32,7 +35,7 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
address := ip.AsAddress() address := ip.AsAddress()
if address.Family().IsDomain() { if address.Family().IsDomain() {
return nil, newError("invalid domain address in static hosts: ", address.Domain()).AtWarning() return nil, errors.New("invalid domain address in static hosts: ", address.Domain()).AtWarning()
} }
sh.ips[id] = []net.Address{address} sh.ips[id] = []net.Address{address}
@ -42,7 +45,7 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
for _, mapping := range hosts { for _, mapping := range hosts {
matcher, err := toStrMatcher(mapping.Type, mapping.Domain) matcher, err := toStrMatcher(mapping.Type, mapping.Domain)
if err != nil { if err != nil {
return nil, newError("failed to create domain matcher").Base(err) return nil, errors.New("failed to create domain matcher").Base(err)
} }
id := g.Add(matcher) id := g.Add(matcher)
ips := make([]net.Address, 0, len(mapping.Ip)+1) ips := make([]net.Address, 0, len(mapping.Ip)+1)
@ -53,12 +56,12 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
for _, ip := range mapping.Ip { for _, ip := range mapping.Ip {
addr := net.IPAddress(ip) addr := net.IPAddress(ip)
if addr == nil { if addr == nil {
return nil, newError("invalid IP address in static hosts: ", ip).AtWarning() return nil, errors.New("invalid IP address in static hosts: ", ip).AtWarning()
} }
ips = append(ips, addr) ips = append(ips, addr)
} }
default: default:
return nil, newError("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning() return nil, errors.New("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning()
} }
sh.ips[id] = ips sh.ips[id] = ips
@ -90,7 +93,7 @@ func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) [
case len(addrs) == 0: // Not recorded in static hosts, return nil case len(addrs) == 0: // Not recorded in static hosts, return nil
return nil return nil
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
newError("found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it").AtDebug().WriteToLog() errors.LogDebug(context.Background(), "found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it")
if maxDepth > 0 { if maxDepth > 0 {
unwrapped := h.lookup(addrs[0].Domain(), option, maxDepth-1) unwrapped := h.lookup(addrs[0].Domain(), option, maxDepth-1)
if unwrapped != nil { if unwrapped != nil {

22
app/dns/nameserver.go

@ -64,7 +64,7 @@ func NewServer(dest net.Destination, dispatcher routing.Dispatcher, queryStrateg
if dest.Network == net.Network_UDP { // UDP classic DNS mode if dest.Network == net.Network_UDP { // UDP classic DNS mode
return NewClassicNameServer(dest, dispatcher), nil return NewClassicNameServer(dest, dispatcher), nil
} }
return nil, newError("No available name server could be created from ", dest).AtWarning() return nil, errors.New("No available name server could be created from ", dest).AtWarning()
} }
// NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs. // NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs.
@ -82,7 +82,7 @@ func NewClient(
// Create a new server for each client for now // Create a new server for each client for now
server, err := NewServer(ns.Address.AsDestination(), dispatcher, ns.GetQueryStrategy()) server, err := NewServer(ns.Address.AsDestination(), dispatcher, ns.GetQueryStrategy())
if err != nil { if err != nil {
return newError("failed to create nameserver").Base(err).AtWarning() return errors.New("failed to create nameserver").Base(err).AtWarning()
} }
// Priotize local domains with specific TLDs or without any dot to local DNS // Priotize local domains with specific TLDs or without any dot to local DNS
@ -111,7 +111,7 @@ func NewClient(
for _, domain := range ns.PrioritizedDomain { for _, domain := range ns.PrioritizedDomain {
domainRule, err := toStrMatcher(domain.Type, domain.Domain) domainRule, err := toStrMatcher(domain.Type, domain.Domain)
if err != nil { if err != nil {
return newError("failed to create prioritized domain").Base(err).AtWarning() return errors.New("failed to create prioritized domain").Base(err).AtWarning()
} }
originalRuleIdx := ruleCurr originalRuleIdx := ruleCurr
if ruleCurr < len(ns.OriginalRules) { if ruleCurr < len(ns.OriginalRules) {
@ -130,7 +130,7 @@ func NewClient(
} }
err = updateDomainRule(domainRule, originalRuleIdx, *matcherInfos) err = updateDomainRule(domainRule, originalRuleIdx, *matcherInfos)
if err != nil { if err != nil {
return newError("failed to create prioritized domain").Base(err).AtWarning() return errors.New("failed to create prioritized domain").Base(err).AtWarning()
} }
} }
@ -139,7 +139,7 @@ func NewClient(
for _, geoip := range ns.Geoip { for _, geoip := range ns.Geoip {
matcher, err := container.Add(geoip) matcher, err := container.Add(geoip)
if err != nil { if err != nil {
return newError("failed to create ip matcher").Base(err).AtWarning() return errors.New("failed to create ip matcher").Base(err).AtWarning()
} }
matchers = append(matchers, matcher) matchers = append(matchers, matcher)
} }
@ -147,9 +147,9 @@ func NewClient(
if len(clientIP) > 0 { if len(clientIP) > 0 {
switch ns.Address.Address.GetAddress().(type) { switch ns.Address.Address.GetAddress().(type) {
case *net.IPOrDomain_Domain: case *net.IPOrDomain_Domain:
newError("DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog() errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String())
case *net.IPOrDomain_Ip: case *net.IPOrDomain_Ip:
newError("DNS: client ", ns.Address.Address.GetIp(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog() errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetIp(), " uses clientIP ", clientIP.String())
} }
} }
@ -169,7 +169,7 @@ func NewSimpleClient(ctx context.Context, endpoint *net.Endpoint, clientIP net.I
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
server, err := NewServer(endpoint.AsDestination(), dispatcher, QueryStrategy_USE_IP) server, err := NewServer(endpoint.AsDestination(), dispatcher, QueryStrategy_USE_IP)
if err != nil { if err != nil {
return newError("failed to create nameserver").Base(err).AtWarning() return errors.New("failed to create nameserver").Base(err).AtWarning()
} }
client.server = server client.server = server
client.clientIP = clientIP client.clientIP = clientIP
@ -179,9 +179,9 @@ func NewSimpleClient(ctx context.Context, endpoint *net.Endpoint, clientIP net.I
if len(clientIP) > 0 { if len(clientIP) > 0 {
switch endpoint.Address.GetAddress().(type) { switch endpoint.Address.GetAddress().(type) {
case *net.IPOrDomain_Domain: case *net.IPOrDomain_Domain:
newError("DNS: client ", endpoint.Address.GetDomain(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog() errors.LogInfo(ctx, "DNS: client ", endpoint.Address.GetDomain(), " uses clientIP ", clientIP.String())
case *net.IPOrDomain_Ip: case *net.IPOrDomain_Ip:
newError("DNS: client ", endpoint.Address.GetIp(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog() errors.LogInfo(ctx, "DNS: client ", endpoint.Address.GetIp(), " uses clientIP ", clientIP.String())
} }
} }
@ -222,7 +222,7 @@ func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error)
if len(newIps) == 0 { if len(newIps) == 0 {
return nil, errExpectedIPNonMatch return nil, errExpectedIPNonMatch
} }
newError("domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name()).AtDebug().WriteToLog() errors.LogDebug(context.Background(), "domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name())
return newIps, nil return newIps, nil
} }

25
app/dns/nameserver_doh.go

@ -12,6 +12,7 @@ import (
"time" "time"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
@ -43,7 +44,7 @@ type DoHNameServer struct {
// NewDoHNameServer creates DOH server object for remote resolving. // NewDoHNameServer creates DOH server object for remote resolving.
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (*DoHNameServer, error) { func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (*DoHNameServer, error) {
newError("DNS: created Remote DOH client for ", url.String()).AtInfo().WriteToLog() errors.LogInfo(context.Background(), "DNS: created Remote DOH client for ", url.String())
s := baseDOHNameServer(url, "DOH", queryStrategy) s := baseDOHNameServer(url, "DOH", queryStrategy)
s.dispatcher = dispatcher s.dispatcher = dispatcher
@ -119,7 +120,7 @@ func NewDoHLocalNameServer(url *url.URL, queryStrategy QueryStrategy) *DoHNameSe
Timeout: time.Second * 180, Timeout: time.Second * 180,
Transport: tr, Transport: tr,
} }
newError("DNS: created Local DOH client for ", url.String()).AtInfo().WriteToLog() errors.LogInfo(context.Background(), "DNS: created Local DOH client for ", url.String())
return s return s
} }
@ -150,7 +151,7 @@ func (s *DoHNameServer) Cleanup() error {
defer s.Unlock() defer s.Unlock()
if len(s.ips) == 0 { if len(s.ips) == 0 {
return newError("nothing to do. stopping...") return errors.New("nothing to do. stopping...")
} }
for domain, record := range s.ips { for domain, record := range s.ips {
@ -162,7 +163,7 @@ func (s *DoHNameServer) Cleanup() error {
} }
if record.A == nil && record.AAAA == nil { if record.A == nil && record.AAAA == nil {
newError(s.name, " cleanup ", domain).AtDebug().WriteToLog() errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
delete(s.ips, domain) delete(s.ips, domain)
} else { } else {
s.ips[domain] = record s.ips[domain] = record
@ -205,7 +206,7 @@ func (s *DoHNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
updated = true updated = true
} }
} }
newError(s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed).AtInfo().WriteToLog() errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
if updated { if updated {
s.ips[req.domain] = rec s.ips[req.domain] = rec
@ -225,10 +226,10 @@ func (s *DoHNameServer) newReqID() uint16 {
} }
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, s.name, " querying: ", domain)
if s.name+"." == "DOH//"+domain { if s.name+"." == "DOH//"+domain {
newError(s.name, " tries to resolve itself! Use IP or set \"hosts\" instead.").AtError().WriteToLog(session.ExportIDToError(ctx)) errors.LogError(ctx, s.name, " tries to resolve itself! Use IP or set \"hosts\" instead.")
return return
} }
@ -266,17 +267,17 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP n
b, err := dns.PackMessage(r.msg) b, err := dns.PackMessage(r.msg)
if err != nil { if err != nil {
newError("failed to pack dns query for ", domain).Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain)
return return
} }
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes()) resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
if err != nil { if err != nil {
newError("failed to retrieve response for ", domain).Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain)
return return
} }
rec, err := parseResponse(resp) rec, err := parseResponse(resp)
if err != nil { if err != nil {
newError("failed to handle DOH response for ", domain).Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain)
return return
} }
s.updateIP(r, rec) s.updateIP(r, rec)
@ -361,11 +362,11 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net
} }
if disableCache { if disableCache {
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if err != errRecordNotFound {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err}) log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
return ips, err return ips, err
} }

7
app/dns/nameserver_fakedns.go

@ -3,6 +3,7 @@ package dns
import ( import (
"context" "context"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
@ -25,7 +26,7 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, op
if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) { if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) {
f.fakeDNSEngine = fd f.fakeDNSEngine = fd
}); err != nil { }); err != nil {
return nil, newError("Unable to locate a fake DNS Engine").Base(err).AtError() return nil, errors.New("Unable to locate a fake DNS Engine").Base(err).AtError()
} }
} }
var ips []net.Address var ips []net.Address
@ -37,10 +38,10 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, op
netIP, err := toNetIP(ips) netIP, err := toNetIP(ips)
if err != nil { if err != nil {
return nil, newError("Unable to convert IP to net ip").Base(err).AtError() return nil, errors.New("Unable to convert IP to net ip").Base(err).AtError()
} }
newError(f.Name(), " got answer: ", domain, " -> ", ips).AtInfo().WriteToLog() errors.LogInfo(ctx, f.Name(), " got answer: ", domain, " -> ", ips)
if len(netIP) > 0 { if len(netIP) > 0 {
return netIP, nil return netIP, nil

7
app/dns/nameserver_local.go

@ -5,6 +5,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
@ -19,7 +20,7 @@ type LocalNameServer struct {
const errEmptyResponse = "No address associated with hostname" const errEmptyResponse = "No address associated with hostname"
// QueryIP implements Server. // QueryIP implements Server.
func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) { func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) {
start := time.Now() start := time.Now()
ips, err = s.client.LookupIP(domain, option) ips, err = s.client.LookupIP(domain, option)
@ -28,7 +29,7 @@ func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, op
} }
if len(ips) > 0 { if len(ips) > 0 {
newError("Localhost got answer: ", domain, " -> ", ips).AtInfo().WriteToLog() errors.LogInfo(ctx, "Localhost got answer: ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err}) log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
} }
@ -42,7 +43,7 @@ func (s *LocalNameServer) Name() string {
// NewLocalNameServer creates localdns server object for directly lookup in system DNS. // NewLocalNameServer creates localdns server object for directly lookup in system DNS.
func NewLocalNameServer() *LocalNameServer { func NewLocalNameServer() *LocalNameServer {
newError("DNS: created localhost client").AtInfo().WriteToLog() errors.LogInfo(context.Background(), "DNS: created localhost client")
return &LocalNameServer{ return &LocalNameServer{
client: localdns.New(), client: localdns.New(),
} }

29
app/dns/nameserver_quic.go

@ -12,6 +12,7 @@ import (
"github.com/quic-go/quic-go" "github.com/quic-go/quic-go"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol/dns" "github.com/xtls/xray-core/common/protocol/dns"
@ -45,7 +46,7 @@ type QUICNameServer struct {
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving // NewQUICNameServer creates DNS-over-QUIC client object for local resolving
func NewQUICNameServer(url *url.URL, queryStrategy QueryStrategy) (*QUICNameServer, error) { func NewQUICNameServer(url *url.URL, queryStrategy QueryStrategy) (*QUICNameServer, error) {
newError("DNS: created Local DNS-over-QUIC client for ", url.String()).AtInfo().WriteToLog() errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
var err error var err error
port := net.Port(853) port := net.Port(853)
@ -84,7 +85,7 @@ func (s *QUICNameServer) Cleanup() error {
defer s.Unlock() defer s.Unlock()
if len(s.ips) == 0 { if len(s.ips) == 0 {
return newError("nothing to do. stopping...") return errors.New("nothing to do. stopping...")
} }
for domain, record := range s.ips { for domain, record := range s.ips {
@ -96,7 +97,7 @@ func (s *QUICNameServer) Cleanup() error {
} }
if record.A == nil && record.AAAA == nil { if record.A == nil && record.AAAA == nil {
newError(s.name, " cleanup ", domain).AtDebug().WriteToLog() errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
delete(s.ips, domain) delete(s.ips, domain)
} else { } else {
s.ips[domain] = record s.ips[domain] = record
@ -139,7 +140,7 @@ func (s *QUICNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
updated = true updated = true
} }
} }
newError(s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed).AtInfo().WriteToLog() errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
if updated { if updated {
s.ips[req.domain] = rec s.ips[req.domain] = rec
@ -159,7 +160,7 @@ func (s *QUICNameServer) newReqID() uint16 {
} }
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, s.name, " querying: ", domain)
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
@ -192,7 +193,7 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
b, err := dns.PackMessage(r.msg) b, err := dns.PackMessage(r.msg)
if err != nil { if err != nil {
newError("failed to pack dns query").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to pack dns query")
return return
} }
@ -203,13 +204,13 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
conn, err := s.openStream(dnsCtx) conn, err := s.openStream(dnsCtx)
if err != nil { if err != nil {
newError("failed to open quic connection").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to open quic connection")
return return
} }
_, err = conn.Write(dnsReqBuf.Bytes()) _, err = conn.Write(dnsReqBuf.Bytes())
if err != nil { if err != nil {
newError("failed to send query").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to send query")
return return
} }
@ -219,25 +220,25 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
defer respBuf.Release() defer respBuf.Release()
n, err := respBuf.ReadFullFrom(conn, 2) n, err := respBuf.ReadFullFrom(conn, 2)
if err != nil && n == 0 { if err != nil && n == 0 {
newError("failed to read response length").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to read response length")
return return
} }
var length int16 var length int16
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length) err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
if err != nil { if err != nil {
newError("failed to parse response length").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to parse response length")
return return
} }
respBuf.Clear() respBuf.Clear()
n, err = respBuf.ReadFullFrom(conn, int32(length)) n, err = respBuf.ReadFullFrom(conn, int32(length))
if err != nil && n == 0 { if err != nil && n == 0 {
newError("failed to read response length").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to read response length")
return return
} }
rec, err := parseResponse(respBuf.Bytes()) rec, err := parseResponse(respBuf.Bytes())
if err != nil { if err != nil {
newError("failed to handle response").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to handle response")
return return
} }
s.updateIP(r, rec) s.updateIP(r, rec)
@ -296,11 +297,11 @@ func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP ne
} }
if disableCache { if disableCache {
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if err != errRecordNotFound {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err}) log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
return ips, err return ips, err
} }

27
app/dns/nameserver_tcp.go

@ -11,6 +11,7 @@ import (
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
@ -114,7 +115,7 @@ func (s *TCPNameServer) Cleanup() error {
defer s.Unlock() defer s.Unlock()
if len(s.ips) == 0 { if len(s.ips) == 0 {
return newError("nothing to do. stopping...") return errors.New("nothing to do. stopping...")
} }
for domain, record := range s.ips { for domain, record := range s.ips {
@ -126,7 +127,7 @@ func (s *TCPNameServer) Cleanup() error {
} }
if record.A == nil && record.AAAA == nil { if record.A == nil && record.AAAA == nil {
newError(s.name, " cleanup ", domain).AtDebug().WriteToLog() errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
delete(s.ips, domain) delete(s.ips, domain)
} else { } else {
s.ips[domain] = record s.ips[domain] = record
@ -169,7 +170,7 @@ func (s *TCPNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
updated = true updated = true
} }
} }
newError(s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed).AtInfo().WriteToLog() errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
if updated { if updated {
s.ips[req.domain] = rec s.ips[req.domain] = rec
@ -189,7 +190,7 @@ func (s *TCPNameServer) newReqID() uint16 {
} }
func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
newError(s.name, " querying DNS for: ", domain).AtDebug().WriteToLog(session.ExportIDToError(ctx)) errors.LogDebug(ctx, s.name, " querying DNS for: ", domain)
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
@ -219,13 +220,13 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP n
b, err := dns.PackMessage(r.msg) b, err := dns.PackMessage(r.msg)
if err != nil { if err != nil {
newError("failed to pack dns query").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to pack dns query")
return return
} }
conn, err := s.dial(dnsCtx) conn, err := s.dial(dnsCtx)
if err != nil { if err != nil {
newError("failed to dial namesever").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to dial namesever")
return return
} }
defer conn.Close() defer conn.Close()
@ -236,7 +237,7 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP n
_, err = conn.Write(dnsReqBuf.Bytes()) _, err = conn.Write(dnsReqBuf.Bytes())
if err != nil { if err != nil {
newError("failed to send query").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to send query")
return return
} }
dnsReqBuf.Release() dnsReqBuf.Release()
@ -245,25 +246,25 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP n
defer respBuf.Release() defer respBuf.Release()
n, err := respBuf.ReadFullFrom(conn, 2) n, err := respBuf.ReadFullFrom(conn, 2)
if err != nil && n == 0 { if err != nil && n == 0 {
newError("failed to read response length").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to read response length")
return return
} }
var length int16 var length int16
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length) err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
if err != nil { if err != nil {
newError("failed to parse response length").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to parse response length")
return return
} }
respBuf.Clear() respBuf.Clear()
n, err = respBuf.ReadFullFrom(conn, int32(length)) n, err = respBuf.ReadFullFrom(conn, int32(length))
if err != nil && n == 0 { if err != nil && n == 0 {
newError("failed to read response length").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to read response length")
return return
} }
rec, err := parseResponse(respBuf.Bytes()) rec, err := parseResponse(respBuf.Bytes())
if err != nil { if err != nil {
newError("failed to parse DNS over TCP response").Base(err).AtError().WriteToLog() errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
return return
} }
@ -319,11 +320,11 @@ func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, clientIP net
} }
if disableCache { if disableCache {
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if err != errRecordNotFound {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err}) log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
return ips, err return ips, err
} }

22
app/dns/nameserver_udp.go

@ -8,11 +8,11 @@ import (
"time" "time"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol/dns" "github.com/xtls/xray-core/common/protocol/dns"
udp_proto "github.com/xtls/xray-core/common/protocol/udp" udp_proto "github.com/xtls/xray-core/common/protocol/udp"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal/pubsub" "github.com/xtls/xray-core/common/signal/pubsub"
"github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/common/task"
dns_feature "github.com/xtls/xray-core/features/dns" dns_feature "github.com/xtls/xray-core/features/dns"
@ -53,7 +53,7 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
Execute: s.Cleanup, Execute: s.Cleanup,
} }
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse) s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
newError("DNS: created UDP client initialized for ", address.NetAddr()).AtInfo().WriteToLog() errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
return s return s
} }
@ -69,7 +69,7 @@ func (s *ClassicNameServer) Cleanup() error {
defer s.Unlock() defer s.Unlock()
if len(s.ips) == 0 && len(s.requests) == 0 { if len(s.ips) == 0 && len(s.requests) == 0 {
return newError(s.name, " nothing to do. stopping...") return errors.New(s.name, " nothing to do. stopping...")
} }
for domain, record := range s.ips { for domain, record := range s.ips {
@ -81,7 +81,7 @@ func (s *ClassicNameServer) Cleanup() error {
} }
if record.A == nil && record.AAAA == nil { if record.A == nil && record.AAAA == nil {
newError(s.name, " cleanup ", domain).AtDebug().WriteToLog() errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
delete(s.ips, domain) delete(s.ips, domain)
} else { } else {
s.ips[domain] = record s.ips[domain] = record
@ -109,7 +109,7 @@ func (s *ClassicNameServer) Cleanup() error {
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) { func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
ipRec, err := parseResponse(packet.Payload.Bytes()) ipRec, err := parseResponse(packet.Payload.Bytes())
if err != nil { if err != nil {
newError(s.name, " fail to parse responded DNS udp").AtError().WriteToLog() errors.LogError(ctx, s.name, " fail to parse responded DNS udp")
return return
} }
@ -122,7 +122,7 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
} }
s.Unlock() s.Unlock()
if !ok { if !ok {
newError(s.name, " cannot find the pending request").AtError().WriteToLog() errors.LogError(ctx, s.name, " cannot find the pending request")
return return
} }
@ -135,7 +135,7 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
} }
elapsed := time.Since(req.start) elapsed := time.Since(req.start)
newError(s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed).AtInfo().WriteToLog() errors.LogInfo(ctx, s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
if len(req.domain) > 0 && (rec.A != nil || rec.AAAA != nil) { if len(req.domain) > 0 && (rec.A != nil || rec.AAAA != nil) {
s.updateIP(req.domain, &rec) s.updateIP(req.domain, &rec)
} }
@ -160,7 +160,7 @@ func (s *ClassicNameServer) updateIP(domain string, newRec *record) {
} }
if updated { if updated {
newError(s.name, " updating IP records for domain:", domain).AtDebug().WriteToLog() errors.LogDebug(context.Background(), s.name, " updating IP records for domain:", domain)
s.ips[domain] = rec s.ips[domain] = rec
} }
if newRec.A != nil { if newRec.A != nil {
@ -187,7 +187,7 @@ func (s *ClassicNameServer) addPendingRequest(req *dnsRequest) {
} }
func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
newError(s.name, " querying DNS for: ", domain).AtDebug().WriteToLog(session.ExportIDToError(ctx)) errors.LogDebug(ctx, s.name, " querying DNS for: ", domain)
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
@ -241,11 +241,11 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
if disableCache { if disableCache {
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if err != errRecordNotFound {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err}) log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
return ips, err return ips, err
} }

7
app/log/command/command.go

@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/app/log" "github.com/xtls/xray-core/app/log"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
) )
@ -19,13 +20,13 @@ type LoggerServer struct {
func (s *LoggerServer) RestartLogger(ctx context.Context, request *RestartLoggerRequest) (*RestartLoggerResponse, error) { func (s *LoggerServer) RestartLogger(ctx context.Context, request *RestartLoggerRequest) (*RestartLoggerResponse, error) {
logger := s.V.GetFeature((*log.Instance)(nil)) logger := s.V.GetFeature((*log.Instance)(nil))
if logger == nil { if logger == nil {
return nil, newError("unable to get logger instance") return nil, errors.New("unable to get logger instance")
} }
if err := logger.Close(); err != nil { if err := logger.Close(); err != nil {
return nil, newError("failed to close logger").Base(err) return nil, errors.New("failed to close logger").Base(err)
} }
if err := logger.Start(); err != nil { if err := logger.Start(); err != nil {
return nil, newError("failed to start logger").Base(err) return nil, errors.New("failed to start logger").Base(err)
} }
return &RestartLoggerResponse{}, nil return &RestartLoggerResponse{}, nil
} }

9
app/log/command/errors.generated.go

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

9
app/log/errors.generated.go

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

9
app/log/log.go

@ -7,6 +7,7 @@ import (
"sync" "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
) )
@ -35,7 +36,7 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
return nil, err return nil, err
} }
newError("Logger started").AtDebug().WriteToLog() errors.LogDebug(ctx, "Logger started")
return g, nil return g, nil
} }
@ -77,10 +78,10 @@ func (g *Instance) startInternal() error {
g.active = true g.active = true
if err := g.initAccessLogger(); err != nil { if err := g.initAccessLogger(); err != nil {
return newError("failed to initialize access logger").Base(err).AtWarning() return errors.New("failed to initialize access logger").Base(err).AtWarning()
} }
if err := g.initErrorLogger(); err != nil { if err := g.initErrorLogger(); err != nil {
return newError("failed to initialize error logger").Base(err).AtWarning() return errors.New("failed to initialize error logger").Base(err).AtWarning()
} }
return nil return nil
@ -120,7 +121,7 @@ func (g *Instance) Handle(msg log.Message) {
// Close implements common.Closable.Close(). // Close implements common.Closable.Close().
func (g *Instance) Close() error { func (g *Instance) Close() error {
newError("Logger closing").AtDebug().WriteToLog() errors.LogDebug(context.Background(), "Logger closing")
g.Lock() g.Lock()
defer g.Unlock() defer g.Unlock()

5
app/log/log_creator.go

@ -4,6 +4,7 @@ import (
"sync" "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
) )
@ -19,7 +20,7 @@ var handlerCreatorMapLock = &sync.RWMutex{}
func RegisterHandlerCreator(logType LogType, f HandlerCreator) error { func RegisterHandlerCreator(logType LogType, f HandlerCreator) error {
if f == nil { if f == nil {
return newError("nil HandlerCreator") return errors.New("nil HandlerCreator")
} }
handlerCreatorMapLock.Lock() handlerCreatorMapLock.Lock()
@ -35,7 +36,7 @@ func createHandler(logType LogType, options HandlerCreatorOptions) (log.Handler,
creator, found := handlerCreatorMap[logType] creator, found := handlerCreatorMap[logType]
if !found { if !found {
return nil, newError("unable to create log handler for ", logType) return nil, errors.New("unable to create log handler for ", logType)
} }
return creator(logType, options) return creator(logType, options)
} }

9
app/metrics/errors.generated.go

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

5
app/metrics/metrics.go

@ -10,6 +10,7 @@ import (
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/app/stats"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
@ -93,12 +94,12 @@ func (p *MetricsHandler) Start() error {
go func() { go func() {
if err := http.Serve(listener, http.DefaultServeMux); err != nil { if err := http.Serve(listener, http.DefaultServeMux); err != nil {
newError("failed to start metrics server").Base(err).AtError().WriteToLog() errors.LogErrorInner(context.Background(), err, "failed to start metrics server")
} }
}() }()
if err := p.ohm.RemoveHandler(context.Background(), p.tag); err != nil { if err := p.ohm.RemoveHandler(context.Background(), p.tag); err != nil {
newError("failed to remove existing handler").WriteToLog() errors.LogInfo(context.Background(), "failed to remove existing handler")
} }
return p.ohm.AddHandler(context.Background(), &Outbound{ return p.ohm.AddHandler(context.Background(), &Outbound{

3
app/metrics/outbound.go

@ -5,6 +5,7 @@ import (
"sync" "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
@ -31,7 +32,7 @@ func (l *OutboundListener) add(conn net.Conn) {
func (l *OutboundListener) Accept() (net.Conn, error) { func (l *OutboundListener) Accept() (net.Conn, error) {
select { select {
case <-l.done.Wait(): case <-l.done.Wait():
return nil, newError("listen closed") return nil, errors.New("listen closed")
case c := <-l.buffer: case c := <-l.buffer:
return c, nil return c, nil
} }

12
app/observatory/burst/burstobserver.go

@ -2,15 +2,17 @@ package burst
import ( import (
"context" "context"
"github.com/xtls/xray-core/core" "sync"
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"sync"
) )
type Observer struct { type Observer struct {
@ -66,7 +68,7 @@ func (o *Observer) Start() error {
hs, ok := o.ohm.(outbound.HandlerSelector) hs, ok := o.ohm.(outbound.HandlerSelector)
if !ok { if !ok {
return nil, newError("outbound.Manager is not a HandlerSelector") return nil, errors.New("outbound.Manager is not a HandlerSelector")
} }
outbounds := hs.Select(o.config.SubjectSelector) outbounds := hs.Select(o.config.SubjectSelector)
@ -90,7 +92,7 @@ func New(ctx context.Context, config *Config) (*Observer, error) {
outboundManager = om outboundManager = om
}) })
if err != nil { if err != nil {
return nil, newError("Cannot get depended features").Base(err) return nil, errors.New("Cannot get depended features").Base(err)
} }
hp := NewHealthPing(ctx, config.PingConfig) hp := NewHealthPing(ctx, config.PingConfig)
return &Observer{ return &Observer{

9
app/observatory/burst/errors.generated.go

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

17
app/observatory/burst/healthping.go

@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
) )
// HealthPingSettings holds settings for health Checker // HealthPingSettings holds settings for health Checker
@ -51,7 +52,7 @@ func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing {
if settings.Interval == 0 { if settings.Interval == 0 {
settings.Interval = time.Duration(1) * time.Minute settings.Interval = time.Duration(1) * time.Minute
} else if settings.Interval < 10 { } else if settings.Interval < 10 {
newError("health check interval is too small, 10s is applied").AtWarning().WriteToLog() errors.LogWarning(ctx, "health check interval is too small, 10s is applied")
settings.Interval = time.Duration(10) * time.Second settings.Interval = time.Duration(10) * time.Second
} }
if settings.SamplingCount <= 0 { if settings.SamplingCount <= 0 {
@ -82,7 +83,7 @@ func (h *HealthPing) StartScheduler(selector func() ([]string, error)) {
go func() { go func() {
tags, err := selector() tags, err := selector()
if err != nil { if err != nil {
newError("error select outbounds for initial health check: ", err).AtWarning().WriteToLog() errors.LogWarning(h.ctx, "error select outbounds for initial health check: ", err)
return return
} }
h.Check(tags) h.Check(tags)
@ -93,7 +94,7 @@ func (h *HealthPing) StartScheduler(selector func() ([]string, error)) {
go func() { go func() {
tags, err := selector() tags, err := selector()
if err != nil { if err != nil {
newError("error select outbounds for scheduled health check: ", err).AtWarning().WriteToLog() errors.LogWarning(h.ctx, "error select outbounds for scheduled health check: ", err)
return return
} }
h.doCheck(tags, interval, h.Settings.SamplingCount) h.doCheck(tags, interval, h.Settings.SamplingCount)
@ -125,7 +126,7 @@ func (h *HealthPing) Check(tags []string) error {
if len(tags) == 0 { if len(tags) == 0 {
return nil return nil
} }
newError("perform one-time health check for tags ", tags).AtInfo().WriteToLog() errors.LogInfo(h.ctx, "perform one-time health check for tags ", tags)
h.doCheck(tags, 0, 1) h.doCheck(tags, 0, 1)
return nil return nil
} }
@ -158,7 +159,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
delay = time.Duration(dice.Roll(int(duration))) delay = time.Duration(dice.Roll(int(duration)))
} }
time.AfterFunc(delay, func() { time.AfterFunc(delay, func() {
newError("checking ", handler).AtDebug().WriteToLog() errors.LogDebug(h.ctx, "checking ", handler)
delay, err := client.MeasureDelay() delay, err := client.MeasureDelay()
if err == nil { if err == nil {
ch <- &rtt{ ch <- &rtt{
@ -168,19 +169,19 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
return return
} }
if !h.checkConnectivity() { if !h.checkConnectivity() {
newError("network is down").AtWarning().WriteToLog() errors.LogWarning(h.ctx, "network is down")
ch <- &rtt{ ch <- &rtt{
handler: handler, handler: handler,
value: 0, value: 0,
} }
return return
} }
newError(fmt.Sprintf( errors.LogWarning(h.ctx, fmt.Sprintf(
"error ping %s with %s: %s", "error ping %s with %s: %s",
h.Settings.Destination, h.Settings.Destination,
handler, handler,
err, err,
)).AtWarning().WriteToLog() ))
ch <- &rtt{ ch <- &rtt{
handler: handler, handler: handler,
value: rttFailed, value: rttFailed,

9
app/observatory/errors.generated.go

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

6
app/observatory/explainErrors.go

@ -8,10 +8,10 @@ type errorCollector struct {
func (e *errorCollector) SubmitError(err error) { func (e *errorCollector) SubmitError(err error) {
if e.errors == nil { if e.errors == nil {
e.errors = newError("underlying connection error").Base(err) e.errors = errors.New("underlying connection error").Base(err)
return return
} }
e.errors = e.errors.Base(newError("underlying connection error").Base(err)) e.errors = e.errors.Base(errors.New("underlying connection error").Base(err))
} }
func newErrorCollector() *errorCollector { func newErrorCollector() *errorCollector {
@ -20,7 +20,7 @@ func newErrorCollector() *errorCollector {
func (e *errorCollector) UnderlyingError() error { func (e *errorCollector) UnderlyingError() error {
if e.errors == nil { if e.errors == nil {
return newError("failed to produce report") return errors.New("failed to produce report")
} }
return e.errors return e.errors
} }

25
app/observatory/observer.go

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
v2net "github.com/xtls/xray-core/common/net" v2net "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
@ -60,7 +61,7 @@ func (o *Observer) background() {
for !o.finished.Done() { for !o.finished.Done() {
hs, ok := o.ohm.(outbound.HandlerSelector) hs, ok := o.ohm.(outbound.HandlerSelector)
if !ok { if !ok {
newError("outbound.Manager is not a HandlerSelector").WriteToLog() errors.LogInfo(o.ctx, "outbound.Manager is not a HandlerSelector")
return return
} }
@ -127,18 +128,18 @@ func (o *Observer) probe(outbound string) ProbeResult {
// MUST use Xray's built in context system // MUST use Xray's built in context system
dest, err := v2net.ParseDestination(network + ":" + addr) dest, err := v2net.ParseDestination(network + ":" + addr)
if err != nil { if err != nil {
return newError("cannot understand address").Base(err) return errors.New("cannot understand address").Base(err)
} }
trackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest) trackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest)
conn, err := tagged.Dialer(trackedCtx, dest, outbound) conn, err := tagged.Dialer(trackedCtx, dest, outbound)
if err != nil { if err != nil {
return newError("cannot dial remote address ", dest).Base(err) return errors.New("cannot dial remote address ", dest).Base(err)
} }
connection = conn connection = conn
return nil return nil
}) })
if taskErr != nil { if taskErr != nil {
return nil, newError("cannot finish connection").Base(taskErr) return nil, errors.New("cannot finish connection").Base(taskErr)
} }
return connection, nil return connection, nil
}, },
@ -161,7 +162,7 @@ func (o *Observer) probe(outbound string) ProbeResult {
} }
response, err := httpClient.Get(probeURL) response, err := httpClient.Get(probeURL)
if err != nil { if err != nil {
return newError("outbound failed to relay connection").Base(err) return errors.New("outbound failed to relay connection").Base(err)
} }
if response.Body != nil { if response.Body != nil {
response.Body.Close() response.Body.Close()
@ -171,15 +172,11 @@ func (o *Observer) probe(outbound string) ProbeResult {
return nil return nil
}) })
if err != nil { if err != nil {
fullerr := newError("underlying connection failed").Base(errorCollectorForRequest.UnderlyingError()) var errorMessage = "the outbound " + outbound + " is dead: GET request failed:" + err.Error() + "with outbound handler report underlying connection failed"
fullerr = newError("with outbound handler report").Base(fullerr) errors.LogInfoInner(o.ctx, errorCollectorForRequest.UnderlyingError(), errorMessage)
fullerr = newError("GET request failed:", err).Base(fullerr) return ProbeResult{Alive: false, LastErrorReason: errorMessage}
fullerr = newError("the outbound ", outbound, " is dead:").Base(fullerr)
fullerr = fullerr.AtInfo()
fullerr.WriteToLog()
return ProbeResult{Alive: false, LastErrorReason: fullerr.Error()}
} }
newError("the outbound ", outbound, " is alive:", GETTime.Seconds()).AtInfo().WriteToLog() errors.LogInfo(o.ctx, "the outbound ", outbound, " is alive:", GETTime.Seconds())
return ProbeResult{Alive: true, Delay: GETTime.Milliseconds()} return ProbeResult{Alive: true, Delay: GETTime.Milliseconds()}
} }
@ -222,7 +219,7 @@ func New(ctx context.Context, config *Config) (*Observer, error) {
outboundManager = om outboundManager = om
}) })
if err != nil { if err != nil {
return nil, newError("Cannot get depended features").Base(err) return nil, errors.New("Cannot get depended features").Base(err)
} }
return &Observer{ return &Observer{
config: config, config: config,

9
app/policy/errors.generated.go

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

19
app/proxyman/command/command.go

@ -4,6 +4,7 @@ import (
"context" "context"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/inbound" "github.com/xtls/xray-core/features/inbound"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
@ -26,7 +27,7 @@ type OutboundOperation interface {
func getInbound(handler inbound.Handler) (proxy.Inbound, error) { func getInbound(handler inbound.Handler) (proxy.Inbound, error) {
gi, ok := handler.(proxy.GetInbound) gi, ok := handler.(proxy.GetInbound)
if !ok { if !ok {
return nil, newError("can't get inbound proxy from handler.") return nil, errors.New("can't get inbound proxy from handler.")
} }
return gi.GetInbound(), nil return gi.GetInbound(), nil
} }
@ -39,11 +40,11 @@ func (op *AddUserOperation) ApplyInbound(ctx context.Context, handler inbound.Ha
} }
um, ok := p.(proxy.UserManager) um, ok := p.(proxy.UserManager)
if !ok { if !ok {
return newError("proxy is not a UserManager") return errors.New("proxy is not a UserManager")
} }
mUser, err := op.User.ToMemoryUser() mUser, err := op.User.ToMemoryUser()
if err != nil { if err != nil {
return newError("failed to parse user").Base(err) return errors.New("failed to parse user").Base(err)
} }
return um.AddUser(ctx, mUser) return um.AddUser(ctx, mUser)
} }
@ -56,7 +57,7 @@ func (op *RemoveUserOperation) ApplyInbound(ctx context.Context, handler inbound
} }
um, ok := p.(proxy.UserManager) um, ok := p.(proxy.UserManager)
if !ok { if !ok {
return newError("proxy is not a UserManager") return errors.New("proxy is not a UserManager")
} }
return um.RemoveUser(ctx, op.Email) return um.RemoveUser(ctx, op.Email)
} }
@ -82,16 +83,16 @@ func (s *handlerServer) RemoveInbound(ctx context.Context, request *RemoveInboun
func (s *handlerServer) AlterInbound(ctx context.Context, request *AlterInboundRequest) (*AlterInboundResponse, error) { func (s *handlerServer) AlterInbound(ctx context.Context, request *AlterInboundRequest) (*AlterInboundResponse, error) {
rawOperation, err := request.Operation.GetInstance() rawOperation, err := request.Operation.GetInstance()
if err != nil { if err != nil {
return nil, newError("unknown operation").Base(err) return nil, errors.New("unknown operation").Base(err)
} }
operation, ok := rawOperation.(InboundOperation) operation, ok := rawOperation.(InboundOperation)
if !ok { if !ok {
return nil, newError("not an inbound operation") return nil, errors.New("not an inbound operation")
} }
handler, err := s.ihm.GetHandler(ctx, request.Tag) handler, err := s.ihm.GetHandler(ctx, request.Tag)
if err != nil { if err != nil {
return nil, newError("failed to get handler: ", request.Tag).Base(err) return nil, errors.New("failed to get handler: ", request.Tag).Base(err)
} }
return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler) return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler)
@ -111,11 +112,11 @@ func (s *handlerServer) RemoveOutbound(ctx context.Context, request *RemoveOutbo
func (s *handlerServer) AlterOutbound(ctx context.Context, request *AlterOutboundRequest) (*AlterOutboundResponse, error) { func (s *handlerServer) AlterOutbound(ctx context.Context, request *AlterOutboundRequest) (*AlterOutboundResponse, error) {
rawOperation, err := request.Operation.GetInstance() rawOperation, err := request.Operation.GetInstance()
if err != nil { if err != nil {
return nil, newError("unknown operation").Base(err) return nil, errors.New("unknown operation").Base(err)
} }
operation, ok := rawOperation.(OutboundOperation) operation, ok := rawOperation.(OutboundOperation)
if !ok { if !ok {
return nil, newError("not an outbound operation") return nil, errors.New("not an outbound operation")
} }
handler := s.ohm.GetHandler(request.Tag) handler := s.ohm.GetHandler(request.Tag)

9
app/proxyman/command/errors.generated.go

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

10
app/proxyman/inbound/always.go

@ -55,7 +55,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
} }
p, ok := rawProxy.(proxy.Inbound) p, ok := rawProxy.(proxy.Inbound)
if !ok { if !ok {
return nil, newError("not an inbound proxy.") return nil, errors.New("not an inbound proxy.")
} }
h := &AlwaysOnInboundHandler{ h := &AlwaysOnInboundHandler{
@ -75,7 +75,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings) mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings)
if err != nil { if err != nil {
return nil, newError("failed to parse stream config").Base(err).AtWarning() return nil, errors.New("failed to parse stream config").Base(err).AtWarning()
} }
if receiverConfig.ReceiveOriginalDestination { if receiverConfig.ReceiveOriginalDestination {
@ -89,7 +89,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
} }
if pl == nil { if pl == nil {
if net.HasNetwork(nl, net.Network_UNIX) { if net.HasNetwork(nl, net.Network_UNIX) {
newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog() errors.LogDebug(ctx, "creating unix domain socket worker on ", address)
worker := &dsWorker{ worker := &dsWorker{
address: address, address: address,
@ -109,7 +109,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
for _, pr := range pl.Range { for _, pr := range pl.Range {
for port := pr.From; port <= pr.To; port++ { for port := pr.From; port <= pr.To; port++ {
if net.HasNetwork(nl, net.Network_TCP) { if net.HasNetwork(nl, net.Network_TCP) {
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog() errors.LogDebug(ctx, "creating stream worker on ", address, ":", port)
worker := &tcpWorker{ worker := &tcpWorker{
address: address, address: address,
@ -167,7 +167,7 @@ func (h *AlwaysOnInboundHandler) Close() error {
} }
errs = append(errs, h.mux.Close()) errs = append(errs, h.mux.Close())
if err := errors.Combine(errs...); err != nil { if err := errors.Combine(errs...); err != nil {
return newError("failed to close all resources").Base(err) return errors.New("failed to close all resources").Base(err)
} }
return nil return nil
} }

11
app/proxyman/inbound/dynamic.go

@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/mux" "github.com/xtls/xray-core/common/mux"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/common/task"
@ -46,7 +47,7 @@ func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *p
mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings) mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings)
if err != nil { if err != nil {
return nil, newError("failed to parse stream settings").Base(err).AtWarning() return nil, errors.New("failed to parse stream settings").Base(err).AtWarning()
} }
if receiverConfig.ReceiveOriginalDestination { if receiverConfig.ReceiveOriginalDestination {
if mss.SocketSettings == nil { if mss.SocketSettings == nil {
@ -94,7 +95,7 @@ func (h *DynamicInboundHandler) closeWorkers(workers []worker) {
for idx, worker := range workers { for idx, worker := range workers {
ports2Del[idx] = worker.Port() ports2Del[idx] = worker.Port()
if err := worker.Close(); err != nil { if err := worker.Close(); err != nil {
newError("failed to close worker").Base(err).WriteToLog() errors.LogInfoInner(h.ctx, err, "failed to close worker")
} }
} }
@ -123,7 +124,7 @@ func (h *DynamicInboundHandler) refresh() error {
port := h.allocatePort() port := h.allocatePort()
rawProxy, err := core.CreateObject(h.v, h.proxyConfig) rawProxy, err := core.CreateObject(h.v, h.proxyConfig)
if err != nil { if err != nil {
newError("failed to create proxy instance").Base(err).AtWarning().WriteToLog() errors.LogWarningInner(h.ctx, err, "failed to create proxy instance")
continue continue
} }
p := rawProxy.(proxy.Inbound) p := rawProxy.(proxy.Inbound)
@ -143,7 +144,7 @@ func (h *DynamicInboundHandler) refresh() error {
ctx: h.ctx, ctx: h.ctx,
} }
if err := worker.Start(); err != nil { if err := worker.Start(); err != nil {
newError("failed to create TCP worker").Base(err).AtWarning().WriteToLog() errors.LogWarningInner(h.ctx, err, "failed to create TCP worker")
continue continue
} }
workers = append(workers, worker) workers = append(workers, worker)
@ -163,7 +164,7 @@ func (h *DynamicInboundHandler) refresh() error {
ctx: h.ctx, ctx: h.ctx,
} }
if err := worker.Start(); err != nil { if err := worker.Start(); err != nil {
newError("failed to create UDP worker").Base(err).AtWarning().WriteToLog() errors.LogWarningInner(h.ctx, err, "failed to create UDP worker")
continue continue
} }
workers = append(workers, worker) workers = append(workers, worker)

9
app/proxyman/inbound/errors.generated.go

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

21
app/proxyman/inbound/inbound.go

@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
@ -43,7 +44,7 @@ func (m *Manager) AddHandler(ctx context.Context, handler inbound.Handler) error
tag := handler.Tag() tag := handler.Tag()
if len(tag) > 0 { if len(tag) > 0 {
if _, found := m.taggedHandlers[tag]; found { if _, found := m.taggedHandlers[tag]; found {
return newError("existing tag found: " + tag) return errors.New("existing tag found: " + tag)
} }
m.taggedHandlers[tag] = handler m.taggedHandlers[tag] = handler
} else { } else {
@ -64,7 +65,7 @@ func (m *Manager) GetHandler(ctx context.Context, tag string) (inbound.Handler,
handler, found := m.taggedHandlers[tag] handler, found := m.taggedHandlers[tag]
if !found { if !found {
return nil, newError("handler not found: ", tag) return nil, errors.New("handler not found: ", tag)
} }
return handler, nil return handler, nil
} }
@ -80,7 +81,7 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
if handler, found := m.taggedHandlers[tag]; found { if handler, found := m.taggedHandlers[tag]; found {
if err := handler.Close(); err != nil { if err := handler.Close(); err != nil {
newError("failed to close handler ", tag).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx)) errors.LogWarningInner(ctx, err, "failed to close handler ", tag)
} }
delete(m.taggedHandlers, tag) delete(m.taggedHandlers, tag)
return nil return nil
@ -117,20 +118,20 @@ func (m *Manager) Close() error {
m.running = false m.running = false
var errors []interface{} var errs []interface{}
for _, handler := range m.taggedHandlers { for _, handler := range m.taggedHandlers {
if err := handler.Close(); err != nil { if err := handler.Close(); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
} }
for _, handler := range m.untaggedHandler { for _, handler := range m.untaggedHandler {
if err := handler.Close(); err != nil { if err := handler.Close(); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
} }
if len(errors) > 0 { if len(errs) > 0 {
return newError("failed to close all handlers").Base(newError(serial.Concat(errors...))) return errors.New("failed to close all handlers").Base(errors.New(serial.Concat(errs...)))
} }
return nil return nil
@ -150,7 +151,7 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
receiverSettings, ok := rawReceiverSettings.(*proxyman.ReceiverConfig) receiverSettings, ok := rawReceiverSettings.(*proxyman.ReceiverConfig)
if !ok { if !ok {
return nil, newError("not a ReceiverConfig").AtError() return nil, errors.New("not a ReceiverConfig").AtError()
} }
streamSettings := receiverSettings.StreamSettings streamSettings := receiverSettings.StreamSettings
@ -168,7 +169,7 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
if allocStrategy.Type == proxyman.AllocationStrategy_Random { if allocStrategy.Type == proxyman.AllocationStrategy_Random {
return NewDynamicInboundHandler(ctx, tag, receiverSettings, proxySettings) return NewDynamicInboundHandler(ctx, tag, receiverSettings, proxySettings)
} }
return nil, newError("unknown allocation strategy: ", receiverSettings.AllocationStrategy.Type).AtError() return nil, errors.New("unknown allocation strategy: ", receiverSettings.AllocationStrategy.Type).AtError()
} }
func init() { func init() {

56
app/proxyman/inbound/worker.go

@ -9,6 +9,8 @@ import (
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
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/net"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
@ -58,7 +60,7 @@ func getTProxyType(s *internet.MemoryStreamConfig) internet.SocketConfig_TProxyM
func (w *tcpWorker) callback(conn stat.Connection) { func (w *tcpWorker) callback(conn stat.Connection) {
ctx, cancel := context.WithCancel(w.ctx) ctx, cancel := context.WithCancel(w.ctx)
sid := session.NewID() sid := session.NewID()
ctx = session.ContextWithID(ctx, sid) ctx = c.ContextWithID(ctx, sid)
outbounds := []*session.Outbound{{}} outbounds := []*session.Outbound{{}}
if w.recvOrigDest { if w.recvOrigDest {
@ -67,7 +69,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
case internet.SocketConfig_Redirect: case internet.SocketConfig_Redirect:
d, err := tcp.GetOriginalDestination(conn) d, err := tcp.GetOriginalDestination(conn)
if err != nil { if err != nil {
newError("failed to get original destination").Base(err).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfoInner(ctx, err, "failed to get original destination")
} else { } else {
dest = d dest = d
} }
@ -105,7 +107,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
ctx = session.ContextWithContent(ctx, content) ctx = session.ContextWithContent(ctx, content)
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil { if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfoInner(ctx, err, "connection ends")
} }
cancel() cancel()
conn.Close() conn.Close()
@ -121,24 +123,24 @@ func (w *tcpWorker) Start() error {
go w.callback(conn) go w.callback(conn)
}) })
if err != nil { if err != nil {
return newError("failed to listen TCP on ", w.port).AtWarning().Base(err) return errors.New("failed to listen TCP on ", w.port).AtWarning().Base(err)
} }
w.hub = hub w.hub = hub
return nil return nil
} }
func (w *tcpWorker) Close() error { func (w *tcpWorker) Close() error {
var errors []interface{} var errs []interface{}
if w.hub != nil { if w.hub != nil {
if err := common.Close(w.hub); err != nil { if err := common.Close(w.hub); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
if err := common.Close(w.proxy); err != nil { if err := common.Close(w.proxy); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
} }
if len(errors) > 0 { if len(errs) > 0 {
return newError("failed to close all resources").Base(newError(serial.Concat(errors...))) return errors.New("failed to close all resources").Base(errors.New(serial.Concat(errs...)))
} }
return nil return nil
@ -306,7 +308,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
go func() { go func() {
ctx := w.ctx ctx := w.ctx
sid := session.NewID() sid := session.NewID()
ctx = session.ContextWithID(ctx, sid) ctx = c.ContextWithID(ctx, sid)
outbounds := []*session.Outbound{{}} outbounds := []*session.Outbound{{}}
if originalDest.IsValid() { if originalDest.IsValid() {
@ -327,7 +329,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
} }
ctx = session.ContextWithContent(ctx, content) ctx = session.ContextWithContent(ctx, content)
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil { if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfoInner(ctx, err, "connection ends")
} }
conn.Close() conn.Close()
// conn not removed by checker TODO may be lock worker here is better // conn not removed by checker TODO may be lock worker here is better
@ -358,7 +360,7 @@ func (w *udpWorker) clean() error {
defer w.Unlock() defer w.Unlock()
if len(w.activeConn) == 0 { if len(w.activeConn) == 0 {
return newError("no more connections. stopping...") return errors.New("no more connections. stopping...")
} }
for addr, conn := range w.activeConn { for addr, conn := range w.activeConn {
@ -402,26 +404,26 @@ func (w *udpWorker) Close() error {
w.Lock() w.Lock()
defer w.Unlock() defer w.Unlock()
var errors []interface{} var errs []interface{}
if w.hub != nil { if w.hub != nil {
if err := w.hub.Close(); err != nil { if err := w.hub.Close(); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
} }
if w.checker != nil { if w.checker != nil {
if err := w.checker.Close(); err != nil { if err := w.checker.Close(); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
} }
if err := common.Close(w.proxy); err != nil { if err := common.Close(w.proxy); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
if len(errors) > 0 { if len(errs) > 0 {
return newError("failed to close all resources").Base(newError(serial.Concat(errors...))) return errors.New("failed to close all resources").Base(errors.New(serial.Concat(errs...)))
} }
return nil return nil
} }
@ -452,7 +454,7 @@ type dsWorker struct {
func (w *dsWorker) callback(conn stat.Connection) { func (w *dsWorker) callback(conn stat.Connection) {
ctx, cancel := context.WithCancel(w.ctx) ctx, cancel := context.WithCancel(w.ctx)
sid := session.NewID() sid := session.NewID()
ctx = session.ContextWithID(ctx, sid) ctx = c.ContextWithID(ctx, sid)
if w.uplinkCounter != nil || w.downlinkCounter != nil { if w.uplinkCounter != nil || w.downlinkCounter != nil {
conn = &stat.CounterConnection{ conn = &stat.CounterConnection{
@ -479,11 +481,11 @@ func (w *dsWorker) callback(conn stat.Connection) {
ctx = session.ContextWithContent(ctx, content) ctx = session.ContextWithContent(ctx, content)
if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil { if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil {
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfoInner(ctx, err, "connection ends")
} }
cancel() cancel()
if err := conn.Close(); err != nil { if err := conn.Close(); err != nil {
newError("failed to close connection").Base(err).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfoInner(ctx, err, "failed to close connection")
} }
} }
@ -501,24 +503,24 @@ func (w *dsWorker) Start() error {
go w.callback(conn) go w.callback(conn)
}) })
if err != nil { if err != nil {
return newError("failed to listen Unix Domain Socket on ", w.address).AtWarning().Base(err) return errors.New("failed to listen Unix Domain Socket on ", w.address).AtWarning().Base(err)
} }
w.hub = hub w.hub = hub
return nil return nil
} }
func (w *dsWorker) Close() error { func (w *dsWorker) Close() error {
var errors []interface{} var errs []interface{}
if w.hub != nil { if w.hub != nil {
if err := common.Close(w.hub); err != nil { if err := common.Close(w.hub); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
if err := common.Close(w.proxy); err != nil { if err := common.Close(w.proxy); err != nil {
errors = append(errors, err) errs = append(errs, err)
} }
} }
if len(errors) > 0 { if len(errs) > 0 {
return newError("failed to close all resources").Base(newError(serial.Concat(errors...))) return errors.New("failed to close all resources").Base(errors.New(serial.Concat(errs...)))
} }
return nil return nil

9
app/proxyman/outbound/errors.generated.go

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

43
app/proxyman/outbound/handler.go

@ -3,9 +3,15 @@ package outbound
import ( import (
"context" "context"
"crypto/rand" "crypto/rand"
"errors" goerrors "errors"
"io"
"math/big"
gonet "net"
"os"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/mux" "github.com/xtls/xray-core/common/mux"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@ -21,10 +27,6 @@ import (
"github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/pipe" "github.com/xtls/xray-core/transport/pipe"
"io"
"math/big"
gonet "net"
"os"
) )
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) { func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
@ -87,11 +89,11 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
h.senderSettings = s h.senderSettings = s
mss, err := internet.ToMemoryStreamConfig(s.StreamSettings) mss, err := internet.ToMemoryStreamConfig(s.StreamSettings)
if err != nil { if err != nil {
return nil, newError("failed to parse stream settings").Base(err).AtWarning() return nil, errors.New("failed to parse stream settings").Base(err).AtWarning()
} }
h.streamSettings = mss h.streamSettings = mss
default: default:
return nil, newError("settings is not SenderConfig") return nil, errors.New("settings is not SenderConfig")
} }
} }
@ -107,7 +109,7 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
proxyHandler, ok := rawProxyHandler.(proxy.Outbound) proxyHandler, ok := rawProxyHandler.(proxy.Outbound)
if !ok { if !ok {
return nil, newError("not an outbound handler") return nil, errors.New("not an outbound handler")
} }
if h.senderSettings != nil && h.senderSettings.MultiplexSettings != nil { if h.senderSettings != nil && h.senderSettings.MultiplexSettings != nil {
@ -170,7 +172,7 @@ func (h *Handler) Tag() string {
// Dispatch implements proxy.Outbound.Dispatch. // Dispatch implements proxy.Outbound.Dispatch.
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) { func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil && ob.OriginalTarget.Address != ob.Target.Address { if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil && ob.OriginalTarget.Address != ob.Target.Address {
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address} link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address} link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
@ -178,16 +180,16 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
if h.mux != nil { if h.mux != nil {
test := func(err error) { test := func(err error) {
if err != nil { if err != nil {
err := newError("failed to process mux outbound traffic").Base(err) err := errors.New("failed to process mux outbound traffic").Base(err)
session.SubmitOutboundErrorToOriginator(ctx, err) session.SubmitOutboundErrorToOriginator(ctx, err)
err.WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, err.Error())
common.Interrupt(link.Writer) common.Interrupt(link.Writer)
} }
} }
if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 { if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 {
switch h.udp443 { switch h.udp443 {
case "reject": case "reject":
test(newError("XUDP rejected UDP/443 traffic").AtInfo()) test(errors.New("XUDP rejected UDP/443 traffic").AtInfo())
return return
case "skip": case "skip":
goto out goto out
@ -208,15 +210,15 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
out: out:
err := h.proxy.Process(ctx, link, h) err := h.proxy.Process(ctx, link, h)
if err != nil { if err != nil {
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrClosedPipe) || errors.Is(err, context.Canceled) { if goerrors.Is(err, io.EOF) || goerrors.Is(err, io.ErrClosedPipe) || goerrors.Is(err, context.Canceled) {
err = nil err = nil
} }
} }
if err != nil { if err != nil {
// Ensure outbound ray is properly closed. // Ensure outbound ray is properly closed.
err := newError("failed to process outbound traffic").Base(err) err := errors.New("failed to process outbound traffic").Base(err)
session.SubmitOutboundErrorToOriginator(ctx, err) session.SubmitOutboundErrorToOriginator(ctx, err)
err.WriteToLog(session.ExportIDToError(ctx)) errors.LogInfo(ctx, err.Error())
common.Interrupt(link.Writer) common.Interrupt(link.Writer)
} else { } else {
common.Close(link.Writer) common.Close(link.Writer)
@ -243,11 +245,11 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
tag := h.senderSettings.ProxySettings.Tag tag := h.senderSettings.ProxySettings.Tag
handler := h.outboundManager.GetHandler(tag) handler := h.outboundManager.GetHandler(tag)
if handler != nil { if handler != nil {
newError("proxying to ", tag, " for dest ", dest).AtDebug().WriteToLog(session.ExportIDToError(ctx)) errors.LogDebug(ctx, "proxying to ", tag, " for dest ", dest)
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ctx = session.ContextWithOutbounds(ctx, append(outbounds, &session.Outbound{ ctx = session.ContextWithOutbounds(ctx, append(outbounds, &session.Outbound{
Target: dest, Target: dest,
Tag: tag, Tag: tag,
})) // add another outbound in session ctx })) // add another outbound in session ctx
opts := pipe.OptionsFromContext(ctx) opts := pipe.OptionsFromContext(ctx)
uplinkReader, uplinkWriter := pipe.New(opts...) uplinkReader, uplinkWriter := pipe.New(opts...)
@ -264,12 +266,12 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
return h.getStatCouterConnection(conn), nil return h.getStatCouterConnection(conn), nil
} }
newError("failed to get outbound handler with tag: ", tag).AtWarning().WriteToLog(session.ExportIDToError(ctx)) errors.LogWarning(ctx, "failed to get outbound handler with tag: ", tag)
} }
if h.senderSettings.Via != nil { if h.senderSettings.Via != nil {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
if h.senderSettings.ViaCidr == "" { if h.senderSettings.ViaCidr == "" {
ob.Gateway = h.senderSettings.Via.AsAddress() ob.Gateway = h.senderSettings.Via.AsAddress()
} else { //Get a random address. } else { //Get a random address.
@ -285,7 +287,7 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
conn, err := internet.Dial(ctx, dest, h.streamSettings) conn, err := internet.Dial(ctx, dest, h.streamSettings)
conn = h.getStatCouterConnection(conn) conn = h.getStatCouterConnection(conn)
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
ob.Conn = conn ob.Conn = conn
return conn, err return conn, err
} }
@ -317,7 +319,6 @@ func (h *Handler) Close() error {
return nil return nil
} }
func ParseRandomIPv6(address net.Address, prefix string) net.Address { func ParseRandomIPv6(address net.Address, prefix string) net.Address {
_, network, _ := gonet.ParseCIDR(address.IP().String() + "/" + prefix) _, network, _ := gonet.ParseCIDR(address.IP().String() + "/" + prefix)

2
app/proxyman/outbound/outbound.go

@ -115,7 +115,7 @@ func (m *Manager) AddHandler(ctx context.Context, handler outbound.Handler) erro
tag := handler.Tag() tag := handler.Tag()
if len(tag) > 0 { if len(tag) > 0 {
if _, found := m.taggedHandler[tag]; found { if _, found := m.taggedHandler[tag]; found {
return newError("existing tag found: " + tag) return errors.New("existing tag found: " + tag)
} }
m.taggedHandler[tag] = handler m.taggedHandler[tag] = handler
} else { } else {

5
app/proxyman/outbound/uot.go

@ -5,6 +5,7 @@ import (
"os" "os"
"github.com/sagernet/sing/common/uot" "github.com/sagernet/sing/common/uot"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/stat"
@ -12,7 +13,7 @@ import (
func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) { func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) {
if dest.Address == nil { if dest.Address == nil {
return nil, newError("nil destination address") return nil, errors.New("nil destination address")
} }
if !dest.Address.Family().IsDomain() { if !dest.Address.Family().IsDomain() {
return nil, os.ErrInvalid return nil, os.ErrInvalid
@ -27,7 +28,7 @@ func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (s
} }
packetConn, err := internet.ListenSystemPacket(ctx, &net.UDPAddr{IP: net.AnyIP.IP(), Port: 0}, h.streamSettings.SocketSettings) packetConn, err := internet.ListenSystemPacket(ctx, &net.UDPAddr{IP: net.AnyIP.IP(), Port: 0}, h.streamSettings.SocketSettings)
if err != nil { if err != nil {
return nil, newError("unable to listen socket").Base(err) return nil, errors.New("unable to listen socket").Base(err)
} }
conn := uot.NewServerConn(packetConn, uotVersion) conn := uot.NewServerConn(packetConn, uotVersion)
return h.getStatCouterConnection(conn), nil return h.getStatCouterConnection(conn), nil

9
app/reverse/bridge.go

@ -4,6 +4,7 @@ import (
"context" "context"
"time" "time"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/mux" "github.com/xtls/xray-core/common/mux"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
@ -26,10 +27,10 @@ type Bridge struct {
// NewBridge creates a new Bridge instance. // NewBridge creates a new Bridge instance.
func NewBridge(config *BridgeConfig, dispatcher routing.Dispatcher) (*Bridge, error) { func NewBridge(config *BridgeConfig, dispatcher routing.Dispatcher) (*Bridge, error) {
if config.Tag == "" { if config.Tag == "" {
return nil, newError("bridge tag is empty") return nil, errors.New("bridge tag is empty")
} }
if config.Domain == "" { if config.Domain == "" {
return nil, newError("bridge domain is empty") return nil, errors.New("bridge domain is empty")
} }
b := &Bridge{ b := &Bridge{
@ -74,7 +75,7 @@ func (b *Bridge) monitor() error {
if numWorker == 0 || numConnections/numWorker > 16 { if numWorker == 0 || numConnections/numWorker > 16 {
worker, err := NewBridgeWorker(b.domain, b.tag, b.dispatcher) worker, err := NewBridgeWorker(b.domain, b.tag, b.dispatcher)
if err != nil { if err != nil {
newError("failed to create bridge worker").Base(err).AtWarning().WriteToLog() errors.LogWarningInner(context.Background(), err, "failed to create bridge worker")
return nil return nil
} }
b.workers = append(b.workers, worker) b.workers = append(b.workers, worker)
@ -157,7 +158,7 @@ func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
for _, b := range mb { for _, b := range mb {
var ctl Control var ctl Control
if err := proto.Unmarshal(b.Bytes(), &ctl); err != nil { if err := proto.Unmarshal(b.Bytes(), &ctl); err != nil {
newError("failed to parse proto message").Base(err).WriteToLog() errors.LogInfoInner(context.Background(), err, "failed to parse proto message")
break break
} }
if ctl.State != w.state { if ctl.State != w.state {

9
app/reverse/errors.generated.go

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

25
app/reverse/portal.go

@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/mux" "github.com/xtls/xray-core/common/mux"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
@ -27,11 +28,11 @@ type Portal struct {
func NewPortal(config *PortalConfig, ohm outbound.Manager) (*Portal, error) { func NewPortal(config *PortalConfig, ohm outbound.Manager) (*Portal, error) {
if config.Tag == "" { if config.Tag == "" {
return nil, newError("portal tag is empty") return nil, errors.New("portal tag is empty")
} }
if config.Domain == "" { if config.Domain == "" {
return nil, newError("portal domain is empty") return nil, errors.New("portal domain is empty")
} }
picker, err := NewStaticMuxPicker() picker, err := NewStaticMuxPicker()
@ -63,20 +64,20 @@ func (p *Portal) Close() error {
func (p *Portal) HandleConnection(ctx context.Context, link *transport.Link) error { func (p *Portal) HandleConnection(ctx context.Context, link *transport.Link) error {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
if ob == nil { if ob == nil {
return newError("outbound metadata not found").AtError() return errors.New("outbound metadata not found").AtError()
} }
if isDomain(ob.Target, p.domain) { if isDomain(ob.Target, p.domain) {
muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{}) muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{})
if err != nil { if err != nil {
return newError("failed to create mux client worker").Base(err).AtWarning() return errors.New("failed to create mux client worker").Base(err).AtWarning()
} }
worker, err := NewPortalWorker(muxClient) worker, err := NewPortalWorker(muxClient)
if err != nil { if err != nil {
return newError("failed to create portal worker").Base(err) return errors.New("failed to create portal worker").Base(err)
} }
p.picker.AddWorker(worker) p.picker.AddWorker(worker)
@ -97,7 +98,7 @@ func (o *Outbound) Tag() string {
func (o *Outbound) Dispatch(ctx context.Context, link *transport.Link) { func (o *Outbound) Dispatch(ctx context.Context, link *transport.Link) {
if err := o.portal.HandleConnection(ctx, link); err != nil { if err := o.portal.HandleConnection(ctx, link); err != nil {
newError("failed to process reverse connection").Base(err).WriteToLog(session.ExportIDToError(ctx)) errors.LogInfoInner(ctx, err, "failed to process reverse connection")
common.Interrupt(link.Writer) common.Interrupt(link.Writer)
} }
} }
@ -149,7 +150,7 @@ func (p *StaticMuxPicker) PickAvailable() (*mux.ClientWorker, error) {
defer p.access.Unlock() defer p.access.Unlock()
if len(p.workers) == 0 { if len(p.workers) == 0 {
return nil, newError("empty worker list") return nil, errors.New("empty worker list")
} }
var minIdx int = -1 var minIdx int = -1
@ -183,7 +184,7 @@ func (p *StaticMuxPicker) PickAvailable() (*mux.ClientWorker, error) {
return p.workers[minIdx].client, nil return p.workers[minIdx].client, nil
} }
return nil, newError("no mux client worker available") return nil, errors.New("no mux client worker available")
} }
func (p *StaticMuxPicker) AddWorker(worker *PortalWorker) { func (p *StaticMuxPicker) AddWorker(worker *PortalWorker) {
@ -216,7 +217,7 @@ func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
Writer: downlinkWriter, Writer: downlinkWriter,
}) })
if !f { if !f {
return nil, newError("unable to dispatch control connection") return nil, errors.New("unable to dispatch control connection")
} }
w := &PortalWorker{ w := &PortalWorker{
client: client, client: client,
@ -233,11 +234,11 @@ func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
func (w *PortalWorker) heartbeat() error { func (w *PortalWorker) heartbeat() error {
if w.client.Closed() { if w.client.Closed() {
return newError("client worker stopped") return errors.New("client worker stopped")
} }
if w.draining || w.writer == nil { if w.draining || w.writer == nil {
return newError("already disposed") return errors.New("already disposed")
} }
msg := &Control{} msg := &Control{}

23
app/router/balancing.go

@ -6,6 +6,7 @@ import (
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
@ -24,8 +25,8 @@ type RoundRobinStrategy struct {
ctx context.Context ctx context.Context
observatory extension.Observatory observatory extension.Observatory
mu sync.Mutex mu sync.Mutex
index int index int
} }
func (s *RoundRobinStrategy) InjectContext(ctx context.Context) { func (s *RoundRobinStrategy) InjectContext(ctx context.Context) {
@ -95,7 +96,7 @@ func (b *Balancer) PickOutbound() (string, error) {
candidates, err := b.SelectOutbounds() candidates, err := b.SelectOutbounds()
if err != nil { if err != nil {
if b.fallbackTag != "" { if b.fallbackTag != "" {
newError("fallback to [", b.fallbackTag, "], due to error: ", err).AtInfo().WriteToLog() errors.LogInfo(context.Background(), "fallback to [", b.fallbackTag, "], due to error: ", err)
return b.fallbackTag, nil return b.fallbackTag, nil
} }
return "", err return "", err
@ -108,11 +109,11 @@ func (b *Balancer) PickOutbound() (string, error) {
} }
if tag == "" { if tag == "" {
if b.fallbackTag != "" { if b.fallbackTag != "" {
newError("fallback to [", b.fallbackTag, "], due to empty tag returned").AtInfo().WriteToLog() errors.LogInfo(context.Background(), "fallback to [", b.fallbackTag, "], due to empty tag returned")
return b.fallbackTag, nil return b.fallbackTag, nil
} }
// will use default handler // will use default handler
return "", newError("balancing strategy returns empty tag") return "", errors.New("balancing strategy returns empty tag")
} }
return tag, nil return tag, nil
} }
@ -127,7 +128,7 @@ func (b *Balancer) InjectContext(ctx context.Context) {
func (b *Balancer) SelectOutbounds() ([]string, error) { func (b *Balancer) SelectOutbounds() ([]string, error) {
hs, ok := b.ohm.(outbound.HandlerSelector) hs, ok := b.ohm.(outbound.HandlerSelector)
if !ok { if !ok {
return nil, newError("outbound.Manager is not a HandlerSelector") return nil, errors.New("outbound.Manager is not a HandlerSelector")
} }
tags := hs.Select(b.selectors) tags := hs.Select(b.selectors)
return tags, nil return tags, nil
@ -139,13 +140,13 @@ func (r *Router) GetPrincipleTarget(tag string) ([]string, error) {
if s, ok := b.strategy.(BalancingPrincipleTarget); ok { if s, ok := b.strategy.(BalancingPrincipleTarget); ok {
candidates, err := b.SelectOutbounds() candidates, err := b.SelectOutbounds()
if err != nil { if err != nil {
return nil, newError("unable to select outbounds").Base(err) return nil, errors.New("unable to select outbounds").Base(err)
} }
return s.GetPrincipleTarget(candidates), nil return s.GetPrincipleTarget(candidates), nil
} }
return nil, newError("unsupported GetPrincipleTarget") return nil, errors.New("unsupported GetPrincipleTarget")
} }
return nil, newError("cannot find tag") return nil, errors.New("cannot find tag")
} }
// SetOverrideTarget implements routing.BalancerOverrider // SetOverrideTarget implements routing.BalancerOverrider
@ -154,7 +155,7 @@ func (r *Router) SetOverrideTarget(tag, target string) error {
b.override.Put(target) b.override.Put(target)
return nil return nil
} }
return newError("cannot find tag") return errors.New("cannot find tag")
} }
// GetOverrideTarget implements routing.BalancerOverrider // GetOverrideTarget implements routing.BalancerOverrider
@ -162,5 +163,5 @@ func (r *Router) GetOverrideTarget(tag string) (string, error) {
if b, ok := r.balancers[tag]; ok { if b, ok := r.balancers[tag]; ok {
return b.override.Get(), nil return b.override.Get(), nil
} }
return "", newError("cannot find tag") return "", errors.New("cannot find tag")
} }

4
app/router/balancing_override.go

@ -2,6 +2,8 @@ package router
import ( import (
sync "sync" sync "sync"
"github.com/xtls/xray-core/common/errors"
) )
func (r *Router) OverrideBalancer(balancer string, target string) error { func (r *Router) OverrideBalancer(balancer string, target string) error {
@ -13,7 +15,7 @@ func (r *Router) OverrideBalancer(balancer string, target string) error {
} }
} }
if b == nil { if b == nil {
return newError("balancer '", balancer, "' not found") return errors.New("balancer '", balancer, "' not found")
} }
b.override.Put(target) b.override.Put(target)
return nil return nil

17
app/router/command/command.go

@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
@ -38,7 +39,7 @@ func (s *routingServer) GetBalancerInfo(ctx context.Context, request *GetBalance
{ {
res, err := pt.GetPrincipleTarget(request.GetTag()) res, err := pt.GetPrincipleTarget(request.GetTag())
if err != nil { if err != nil {
newError("unable to obtain principle target").Base(err).AtInfo().WriteToLog() errors.LogInfoInner(ctx, err, "unable to obtain principle target")
} else { } else {
ret.Balancer.PrincipleTarget = &PrincipleTargetInfo{Tag: res} ret.Balancer.PrincipleTarget = &PrincipleTargetInfo{Tag: res}
} }
@ -51,21 +52,21 @@ func (s *routingServer) OverrideBalancerTarget(ctx context.Context, request *Ove
if bo, ok := s.router.(routing.BalancerOverrider); ok { if bo, ok := s.router.(routing.BalancerOverrider); ok {
return &OverrideBalancerTargetResponse{}, bo.SetOverrideTarget(request.BalancerTag, request.Target) return &OverrideBalancerTargetResponse{}, bo.SetOverrideTarget(request.BalancerTag, request.Target)
} }
return nil, newError("unsupported router implementation") return nil, errors.New("unsupported router implementation")
} }
func (s *routingServer) AddRule(ctx context.Context, request *AddRuleRequest) (*AddRuleResponse, error) { func (s *routingServer) AddRule(ctx context.Context, request *AddRuleRequest) (*AddRuleResponse, error) {
if bo, ok := s.router.(routing.Router); ok { if bo, ok := s.router.(routing.Router); ok {
return &AddRuleResponse{}, bo.AddRule(request.Config, request.ShouldAppend) return &AddRuleResponse{}, bo.AddRule(request.Config, request.ShouldAppend)
} }
return nil, newError("unsupported router implementation") return nil, errors.New("unsupported router implementation")
} }
func (s *routingServer) RemoveRule(ctx context.Context, request *RemoveRuleRequest) (*RemoveRuleResponse, error) { func (s *routingServer) RemoveRule(ctx context.Context, request *RemoveRuleRequest) (*RemoveRuleResponse, error) {
if bo, ok := s.router.(routing.Router); ok { if bo, ok := s.router.(routing.Router); ok {
return &RemoveRuleResponse{}, bo.RemoveRule(request.RuleTag) return &RemoveRuleResponse{}, bo.RemoveRule(request.RuleTag)
} }
return nil, newError("unsupported router implementation") return nil, errors.New("unsupported router implementation")
} }
// NewRoutingServer creates a statistics service with statistics manager. // NewRoutingServer creates a statistics service with statistics manager.
@ -78,7 +79,7 @@ func NewRoutingServer(router routing.Router, routingStats stats.Channel) Routing
func (s *routingServer) TestRoute(ctx context.Context, request *TestRouteRequest) (*RoutingContext, error) { func (s *routingServer) TestRoute(ctx context.Context, request *TestRouteRequest) (*RoutingContext, error) {
if request.RoutingContext == nil { if request.RoutingContext == nil {
return nil, newError("Invalid routing request.") return nil, errors.New("Invalid routing request.")
} }
route, err := s.router.PickRoute(AsRoutingContext(request.RoutingContext)) route, err := s.router.PickRoute(AsRoutingContext(request.RoutingContext))
if err != nil { if err != nil {
@ -93,7 +94,7 @@ func (s *routingServer) TestRoute(ctx context.Context, request *TestRouteRequest
func (s *routingServer) SubscribeRoutingStats(request *SubscribeRoutingStatsRequest, stream RoutingService_SubscribeRoutingStatsServer) error { func (s *routingServer) SubscribeRoutingStats(request *SubscribeRoutingStatsRequest, stream RoutingService_SubscribeRoutingStatsServer) error {
if s.routingStats == nil { if s.routingStats == nil {
return newError("Routing statistics not enabled.") return errors.New("Routing statistics not enabled.")
} }
genMessage := AsProtobufMessage(request.FieldSelectors) genMessage := AsProtobufMessage(request.FieldSelectors)
subscriber, err := stats.SubscribeRunnableChannel(s.routingStats) subscriber, err := stats.SubscribeRunnableChannel(s.routingStats)
@ -105,11 +106,11 @@ func (s *routingServer) SubscribeRoutingStats(request *SubscribeRoutingStatsRequ
select { select {
case value, ok := <-subscriber: case value, ok := <-subscriber:
if !ok { if !ok {
return newError("Upstream closed the subscriber channel.") return errors.New("Upstream closed the subscriber channel.")
} }
route, ok := value.(routing.Route) route, ok := value.(routing.Route)
if !ok { if !ok {
return newError("Upstream sent malformed statistics.") return errors.New("Upstream sent malformed statistics.")
} }
err := stream.Send(genMessage(route)) err := stream.Send(genMessage(route))
if err != nil { if err != nil {

9
app/router/command/errors.generated.go

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

7
app/router/condition.go

@ -4,6 +4,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/strmatcher" "github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
@ -49,12 +50,12 @@ var matcherTypeMap = map[Domain_Type]strmatcher.Type{
func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) { func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) {
matcherType, f := matcherTypeMap[domain.Type] matcherType, f := matcherTypeMap[domain.Type]
if !f { if !f {
return nil, newError("unsupported domain type", domain.Type) return nil, errors.New("unsupported domain type", domain.Type)
} }
matcher, err := matcherType.New(domain.Value) matcher, err := matcherType.New(domain.Value)
if err != nil { if err != nil {
return nil, newError("failed to create domain matcher").Base(err) return nil, errors.New("failed to create domain matcher").Base(err)
} }
return matcher, nil return matcher, nil
@ -69,7 +70,7 @@ func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
for _, d := range domains { for _, d := range domains {
matcherType, f := matcherTypeMap[d.Type] matcherType, f := matcherTypeMap[d.Type]
if !f { if !f {
return nil, newError("unsupported domain type", d.Type) return nil, errors.New("unsupported domain type", d.Type)
} }
_, err := g.AddPattern(d.Value, matcherType) _, err := g.AddPattern(d.Value, matcherType)
if err != nil { if err != nil {

14
app/router/config.go

@ -1,9 +1,11 @@
package router package router
import ( import (
"context"
"regexp" "regexp"
"strings" "strings"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
@ -36,7 +38,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
case "linear": case "linear":
matcher, err := NewDomainMatcher(rr.Domain) matcher, err := NewDomainMatcher(rr.Domain)
if err != nil { if err != nil {
return nil, newError("failed to build domain condition").Base(err) return nil, errors.New("failed to build domain condition").Base(err)
} }
conds.Add(matcher) conds.Add(matcher)
case "mph", "hybrid": case "mph", "hybrid":
@ -44,9 +46,9 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
default: default:
matcher, err := NewMphMatcherGroup(rr.Domain) matcher, err := NewMphMatcherGroup(rr.Domain)
if err != nil { if err != nil {
return nil, newError("failed to build domain condition with MphDomainMatcher").Base(err) return nil, errors.New("failed to build domain condition with MphDomainMatcher").Base(err)
} }
newError("MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)").AtDebug().WriteToLog() errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)")
conds.Add(matcher) conds.Add(matcher)
} }
} }
@ -116,7 +118,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
} }
if conds.Len() == 0 { if conds.Len() == 0 {
return nil, newError("this rule has no effective fields").AtWarning() return nil, errors.New("this rule has no effective fields").AtWarning()
} }
return conds, nil return conds, nil
@ -146,7 +148,7 @@ func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatch
} }
s, ok := i.(*StrategyLeastLoadConfig) s, ok := i.(*StrategyLeastLoadConfig)
if !ok { if !ok {
return nil, newError("not a StrategyLeastLoadConfig").AtError() return nil, errors.New("not a StrategyLeastLoadConfig").AtError()
} }
leastLoadStrategy := NewLeastLoadStrategy(s) leastLoadStrategy := NewLeastLoadStrategy(s)
return &Balancer{ return &Balancer{
@ -165,6 +167,6 @@ func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatch
strategy: &RandomStrategy{FallbackTag: br.FallbackTag}, strategy: &RandomStrategy{FallbackTag: br.FallbackTag},
}, nil }, nil
default: default:
return nil, newError("unrecognized balancer type") return nil, errors.New("unrecognized balancer type")
} }
} }

9
app/router/errors.generated.go

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

13
app/router/router.go

@ -7,6 +7,7 @@ import (
sync "sync" sync "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
@ -68,7 +69,7 @@ func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm out
if len(btag) > 0 { if len(btag) > 0 {
brule, found := r.balancers[btag] brule, found := r.balancers[btag]
if !found { if !found {
return newError("balancer ", btag, " not found") return errors.New("balancer ", btag, " not found")
} }
rr.Balancer = brule rr.Balancer = brule
} }
@ -101,7 +102,7 @@ func (r *Router) AddRule(config *serial.TypedMessage, shouldAppend bool) error {
if c, ok := inst.(*Config); ok { if c, ok := inst.(*Config); ok {
return r.ReloadRules(c, shouldAppend) return r.ReloadRules(c, shouldAppend)
} }
return newError("AddRule: config type error") return errors.New("AddRule: config type error")
} }
func (r *Router) ReloadRules(config *Config, shouldAppend bool) error { func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
@ -115,7 +116,7 @@ func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
for _, rule := range config.BalancingRule { for _, rule := range config.BalancingRule {
_, found := r.balancers[rule.Tag] _, found := r.balancers[rule.Tag]
if found { if found {
return newError("duplicate balancer tag") return errors.New("duplicate balancer tag")
} }
balancer, err := rule.Build(r.ohm, r.dispatcher) balancer, err := rule.Build(r.ohm, r.dispatcher)
if err != nil { if err != nil {
@ -127,7 +128,7 @@ func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
for _, rule := range config.Rule { for _, rule := range config.Rule {
if r.RuleExists(rule.GetRuleTag()) { if r.RuleExists(rule.GetRuleTag()) {
return newError("duplicate ruleTag ", rule.GetRuleTag()) return errors.New("duplicate ruleTag ", rule.GetRuleTag())
} }
cond, err := rule.BuildCondition() cond, err := rule.BuildCondition()
if err != nil { if err != nil {
@ -142,7 +143,7 @@ func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
if len(btag) > 0 { if len(btag) > 0 {
brule, found := r.balancers[btag] brule, found := r.balancers[btag]
if !found { if !found {
return newError("balancer ", btag, " not found") return errors.New("balancer ", btag, " not found")
} }
rr.Balancer = brule rr.Balancer = brule
} }
@ -178,7 +179,7 @@ func (r *Router) RemoveRule(tag string) error {
r.rules = newRules r.rules = newRules
return nil return nil
} }
return newError("empty tag name!") return errors.New("empty tag name!")
} }
func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) { func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) {

7
app/router/strategy_leastload.go

@ -9,6 +9,7 @@ import (
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
) )
@ -95,7 +96,7 @@ func (s *LeastLoadStrategy) pickOutbounds(candidates []string) []*node {
// with 'balancer.fallbackTag', it means: selects qualified nodes or use the fallback. // with 'balancer.fallbackTag', it means: selects qualified nodes or use the fallback.
func (s *LeastLoadStrategy) selectLeastLoad(nodes []*node) []*node { func (s *LeastLoadStrategy) selectLeastLoad(nodes []*node) []*node {
if len(nodes) == 0 { if len(nodes) == 0 {
newError("least load: no qualified outbound").AtInfo().WriteToLog() errors.LogInfo(s.ctx, "least load: no qualified outbound")
return nil return nil
} }
expected := int(s.settings.Expected) expected := int(s.settings.Expected)
@ -123,7 +124,7 @@ func (s *LeastLoadStrategy) selectLeastLoad(nodes []*node) []*node {
} }
// don't continue if find expected selects // don't continue if find expected selects
if count >= expected { if count >= expected {
newError("applied baseline: ", baseline).AtDebug().WriteToLog() errors.LogDebug(s.ctx, "applied baseline: ", baseline)
break break
} }
} }
@ -142,7 +143,7 @@ func (s *LeastLoadStrategy) getNodes(candidates []string, maxRTT time.Duration)
} }
observeResult, err := s.observer.GetObservation(s.ctx) observeResult, err := s.observer.GetObservation(s.ctx)
if err != nil { if err != nil {
newError("cannot get observation").Base(err).WriteToLog() errors.LogInfoInner(s.ctx, err, "cannot get observation")
return make([]*node, 0) return make([]*node, 0)
} }

3
app/router/strategy_leastping.go

@ -5,6 +5,7 @@ import (
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
) )
@ -32,7 +33,7 @@ func (l *LeastPingStrategy) PickOutbound(strings []string) string {
observeReport, err := l.observatory.GetObservation(l.ctx) observeReport, err := l.observatory.GetObservation(l.ctx)
if err != nil { if err != nil {
newError("cannot get observe report").Base(err).WriteToLog() errors.LogInfoInner(l.ctx, err, "cannot get observe report")
return "" return ""
} }
outboundsList := outboundList(strings) outboundsList := outboundList(strings)

7
app/router/weight.go

@ -1,10 +1,13 @@
package router package router
import ( import (
"context"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"github.com/xtls/xray-core/common/errors"
) )
type weightScaler func(value, weight float64) float64 type weightScaler func(value, weight float64) float64
@ -64,7 +67,7 @@ func (s *WeightManager) findValue(tag string) float64 {
} }
weight, err := strconv.ParseFloat(numStr, 64) weight, err := strconv.ParseFloat(numStr, 64)
if err != nil { if err != nil {
newError("unexpected error from ParseFloat: ", err).AtError().WriteToLog() errors.LogError(context.Background(), "unexpected error from ParseFloat: ", err)
return s.defaultWeight return s.defaultWeight
} }
return weight return weight
@ -82,7 +85,7 @@ func (s *WeightManager) getMatch(tag, find string, isRegexp bool) string {
} }
r, err := regexp.Compile(find) r, err := regexp.Compile(find)
if err != nil { if err != nil {
newError("invalid regexp: ", find, "err: ", err).AtError().WriteToLog() errors.LogError(context.Background(), "invalid regexp: ", find, "err: ", err)
return "" return ""
} }
return r.FindString(tag) return r.FindString(tag)

3
app/stats/channel.go

@ -5,6 +5,7 @@ import (
"sync" "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
) )
// Channel is an implementation of stats.Channel. // Channel is an implementation of stats.Channel.
@ -44,7 +45,7 @@ func (c *Channel) Subscribe() (chan interface{}, error) {
c.access.Lock() c.access.Lock()
defer c.access.Unlock() defer c.access.Unlock()
if c.subsLimit > 0 && len(c.subscribers) >= c.subsLimit { if c.subsLimit > 0 && len(c.subscribers) >= c.subsLimit {
return nil, newError("Number of subscribers has reached limit") return nil, errors.New("Number of subscribers has reached limit")
} }
subscriber := make(chan interface{}, c.bufferSize) subscriber := make(chan interface{}, c.bufferSize)
c.subscribers = append(c.subscribers, subscriber) c.subscribers = append(c.subscribers, subscriber)

5
app/stats/command/command.go

@ -9,6 +9,7 @@ import (
"github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/app/stats"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/strmatcher" "github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
feature_stats "github.com/xtls/xray-core/features/stats" feature_stats "github.com/xtls/xray-core/features/stats"
@ -31,7 +32,7 @@ func NewStatsServer(manager feature_stats.Manager) StatsServiceServer {
func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) { func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
c := s.stats.GetCounter(request.Name) c := s.stats.GetCounter(request.Name)
if c == nil { if c == nil {
return nil, newError(request.Name, " not found.") return nil, errors.New(request.Name, " not found.")
} }
var value int64 var value int64
if request.Reset_ { if request.Reset_ {
@ -57,7 +58,7 @@ func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest
manager, ok := s.stats.(*stats.Manager) manager, ok := s.stats.(*stats.Manager)
if !ok { if !ok {
return nil, newError("QueryStats only works its own stats.Manager.") return nil, errors.New("QueryStats only works its own stats.Manager.")
} }
manager.VisitCounters(func(name string, c feature_stats.Counter) bool { manager.VisitCounters(func(name string, c feature_stats.Counter) bool {

9
app/stats/command/errors.generated.go

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

9
app/stats/errors.generated.go

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

14
app/stats/stats.go

@ -40,9 +40,9 @@ func (m *Manager) RegisterCounter(name string) (stats.Counter, error) {
defer m.access.Unlock() defer m.access.Unlock()
if _, found := m.counters[name]; found { if _, found := m.counters[name]; found {
return nil, newError("Counter ", name, " already registered.") return nil, errors.New("Counter ", name, " already registered.")
} }
newError("create new counter ", name).AtDebug().WriteToLog() errors.LogDebug(context.Background(), "create new counter ", name)
c := new(Counter) c := new(Counter)
m.counters[name] = c m.counters[name] = c
return c, nil return c, nil
@ -54,7 +54,7 @@ func (m *Manager) UnregisterCounter(name string) error {
defer m.access.Unlock() defer m.access.Unlock()
if _, found := m.counters[name]; found { if _, found := m.counters[name]; found {
newError("remove counter ", name).AtDebug().WriteToLog() errors.LogDebug(context.Background(), "remove counter ", name)
delete(m.counters, name) delete(m.counters, name)
} }
return nil return nil
@ -89,9 +89,9 @@ func (m *Manager) RegisterChannel(name string) (stats.Channel, error) {
defer m.access.Unlock() defer m.access.Unlock()
if _, found := m.channels[name]; found { if _, found := m.channels[name]; found {
return nil, newError("Channel ", name, " already registered.") return nil, errors.New("Channel ", name, " already registered.")
} }
newError("create new channel ", name).AtDebug().WriteToLog() errors.LogDebug(context.Background(), "create new channel ", name)
c := NewChannel(&ChannelConfig{BufferSize: 64, Blocking: false}) c := NewChannel(&ChannelConfig{BufferSize: 64, Blocking: false})
m.channels[name] = c m.channels[name] = c
if m.running { if m.running {
@ -106,7 +106,7 @@ func (m *Manager) UnregisterChannel(name string) error {
defer m.access.Unlock() defer m.access.Unlock()
if c, found := m.channels[name]; found { if c, found := m.channels[name]; found {
newError("remove channel ", name).AtDebug().WriteToLog() errors.LogDebug(context.Background(), "remove channel ", name)
delete(m.channels, name) delete(m.channels, name)
return c.Close() return c.Close()
} }
@ -148,7 +148,7 @@ func (m *Manager) Close() error {
m.running = false m.running = false
errs := []error{} errs := []error{}
for name, channel := range m.channels { for name, channel := range m.channels {
newError("remove channel ", name).AtDebug().WriteToLog() errors.LogDebug(context.Background(), "remove channel ", name)
delete(m.channels, name) delete(m.channels, name)
if err := channel.Close(); err != nil { if err := channel.Close(); err != nil {
errs = append(errs, err) errs = append(errs, err)

5
common/buf/buffer.go

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

2
common/buf/copy.go

@ -120,7 +120,7 @@ func Copy(reader Reader, writer Writer, options ...CopyOption) error {
return nil 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 { func CopyOnceTimeout(reader Reader, writer Writer, timeout time.Duration) error {
timeoutReader, ok := reader.(TimeoutReader) timeoutReader, ok := reader.(TimeoutReader)

4
common/buf/copy_test.go

@ -27,7 +27,7 @@ func TestReadError(t *testing.T) {
t.Error("expected to be ReadError, but not") 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()) t.Fatal("unexpected error message: ", err.Error())
} }
} }
@ -48,7 +48,7 @@ func TestWriteError(t *testing.T) {
t.Error("expected to be WriteError, but not") 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()) t.Fatal("unexpected error message: ", err.Error())
} }
} }

9
common/buf/errors.generated.go

@ -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{})
}

6
common/buf/io.go

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

2
common/buf/reader.go

@ -21,7 +21,7 @@ func readOneUDP(r io.Reader) (*Buffer, error) {
} }
b.Release() 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. // ReadBuffer reads a Buffer from the given reader.

9
common/crypto/auth.go

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

9
common/crypto/errors.generated.go

@ -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

@ -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
}

7
common/drain/drainer.go

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

9
common/drain/errors.generated.go

@ -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{})
}

9
common/errors.generated.go

@ -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{})
}

37
common/errors/errorgen/main.go

@ -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)
}

115
common/errors/errors.go

@ -2,9 +2,11 @@
package errors // import "github.com/xtls/xray-core/common/errors" package errors // import "github.com/xtls/xray-core/common/errors"
import ( import (
"reflect" "context"
"runtime"
"strings" "strings"
c "github.com/xtls/xray-core/common/ctx"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
) )
@ -22,29 +24,13 @@ type hasSeverity interface {
// Error is an error object with underlying error. // Error is an error object with underlying error.
type Error struct { type Error struct {
pathObj interface{}
prefix []interface{} prefix []interface{}
message []interface{} message []interface{}
caller string
inner error inner error
severity log.Severity 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(). // Error implements error.Error().
func (err *Error) Error() string { func (err *Error) Error() string {
builder := strings.Builder{} builder := strings.Builder{}
@ -54,9 +40,8 @@ func (err *Error) Error() string {
builder.WriteString("] ") builder.WriteString("] ")
} }
path := err.pkgPath() if len(err.caller) > 0 {
if len(path) > 0 { builder.WriteString(err.caller)
builder.WriteString(path)
builder.WriteString(": ") builder.WriteString(": ")
} }
@ -129,24 +114,6 @@ func (err *Error) String() string {
return err.Error() 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 { type ExportOptionHolder struct {
SessionID uint32 SessionID uint32
} }
@ -155,10 +122,80 @@ type ExportOption func(*ExportOptionHolder)
// New returns a new error object with message formed from given arguments. // New returns a new error object with message formed from given arguments.
func New(msg ...interface{}) *Error { 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{ return &Error{
message: msg, message: msg,
severity: log.Severity_Info, 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. // Cause returns the root cause of this error.

10
common/errors/errors_test.go

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

22
common/mux/client.go

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

9
common/mux/errors.generated.go

@ -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{})
}

11
common/mux/frame.go

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

3
common/mux/reader.go

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

26
common/mux/server.go

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

6
common/mux/session.go

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

5
common/net/address.go

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

9
common/net/errors.generated.go

@ -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{})
}

6
common/net/port.go

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

9
common/ocsp/errors.generated.go

@ -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{})
}

17
common/ocsp/ocsp.go

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

10
common/platform/ctlcmd/ctlcmd.go

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

9
common/platform/ctlcmd/errors.generated.go

@ -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{})
}

11
common/protocol/address.go

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

9
common/protocol/dns/errors.generated.go

@ -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{})
}

3
common/protocol/dns/io.go

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

9
common/protocol/errors.generated.go

@ -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{})
}

17
common/protocol/tls/cert/cert.go

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

3
common/protocol/tls/cert/cert_test.go

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/task" "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...) cert, err := Generate(nil, opts...)
if err != nil { if err != nil {
return newError("failed to generate TLS certificate").Base(err) return errors.New("failed to generate TLS certificate").Base(err)
} }
if jsonOutput { if jsonOutput {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save