Compare commits

...

89 Commits

Author SHA1 Message Date
RPRX
4c82ef8a1b v1.8.23 2024-07-29 10:23:04 +00:00
mmmray
30af792777 SplitHTTP: Rename three options & Reduce server defaults (#3611)
* maxUploadSize -> scMaxEachPostBytes, default is 1MB on both sides (was 2MB on the server)
* minUploadIntervalMs -> scMinPostsIntervalMs, default is 30ms on the client (no server support for now)
* maxConcurrentUploads -> scMaxConcurrentPosts, default is 100 on both sides (was 200 on the server)
2024-07-29 10:10:29 +00:00
mmmray
33daa0c94b SplitHTTP: Fix wrong config deserialization (#3610)
Testing was conducted only using explicit parameters, and using
testsuite. However, when the parameters are not explicitly set in JSON
config, it seems that `c.MaxUploadSize` will contain `RandRangeConfig {
From: 0, To: 0 }` instead of `nil`, which breaks upload entirely.
2024-07-29 08:50:59 +00:00
RPRX
70383c50cc v1.8.22 2024-07-29 08:22:12 +00:00
mayampi01
521d8ef6a1 Docker: Add multi-arch builds and Loyalsoldier flavor (#3589)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-07-29 07:36:30 +00:00
lelemka0
4531a7e228 CertificateObject: Enable auto-reload for cacert & Add buildChain & Fixes (#3607) 2024-07-29 06:58:58 +00:00
yuhan6665
a342db3e28 Fix a nil pointer in Wireguard client logging (#3608) 2024-07-29 06:43:46 +00:00
RPRX
60553a6c26 SplitHTTP server: Add noSSEHeader
https://github.com/XTLS/Xray-core/pull/3603#issuecomment-2254968219
2024-07-29 06:32:04 +00:00
mmmray
59f6685774 SplitHTTP: More range options, change defaults, enforce maxUploadSize, fix querystring behavior (#3603)
* maxUploadSize and maxConcurrentUploads can now be ranges on the client
* maxUploadSize is now enforced on the server
* the default of maxUploadSize is 2MB on the server, and 1MB on the client
* the default of maxConcurrentUploads is 200 on the server, and 100 on the client
* ranges on the server are treated as a single number. if server is configured as `"1-2"`, server will enforce `2`
* querystrings in `path` are now handled correctly
2024-07-29 04:35:17 +00:00
yuhan6665
4cb2a128db Don't do raw/splice copy in case of MITM 2024-07-24 20:41:40 -04:00
mmmray
8a4217fdf5 SplitHTTP client: Add minUploadInterval (#3592) 2024-07-27 12:52:36 +00:00
mmmray
7cf5ee8afd WS, HU: Remove unnecessary sleep from test (#3600) 2024-07-27 12:38:54 +00:00
mmmray
2becdd6414 SplitHTTP server: Fix panic during concurrent Close and Push (#3593)
When Close and Push are called concurrently, it may happen that Push attempts to write to an already-closed channel, and trigger a panic.

From a user perspective, it results in logs like this:

    http: panic serving 172.19.0.6:50476: send on closed channel

It's probably triggered when download is closed at the same time an upload packet is submitted.

These panics don't crash the server and the inbound is still usable.
2024-07-26 04:36:55 +02:00
hellokindle
edae38c620 Fix SplitHTTP Unix domain socket (#3577)
Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-07-22 22:19:31 +02:00
mayampi01
36f427f22b docker.yml: Set latest to auto to tag release version (#3581) 2024-07-22 16:16:25 +02:00
RPRX
c27d652d80 v1.8.21 2024-07-21 21:32:26 +00:00
RPRX
0f65aa8ed8 Fix SplitHTTP H3 waited for downResponse before uploading
https://github.com/XTLS/Xray-core/issues/3560#issuecomment-2241750579
2024-07-21 20:45:05 +00:00
RPRX
22535d8643 Fix SplitHTTP H3 didn't always reuse QUIC connection
https://github.com/XTLS/Xray-core/issues/3560#issuecomment-2241531502
2024-07-21 08:55:03 +00:00
mmmray
529f206d33 Fix serverside TLS support of SplitHTTP H1/H2 (#3567)
Fix #3566

Also update testsuite so that all tests read and write some data. Opening a connection is not enough to trigger connection errors, because the connection is so lazy.
2024-07-20 19:35:24 -05:00
チセ
964859b4bc SplitHTTP: Remove unnecessary keepalives (#3565)
Remove keep alive since quic-go/http3 doesn't support stream reuse
Discussion see https://t.me/projectXray/3782492

Co-authored-by: Fangliding <Fangliding.fshxy@outlook.com>
Co-authored-by: xqzr <34030394+xqzr@users.noreply.github.com>
Co-authored-by: ll11l1lIllIl1lll <88377095+ll11l1lIllIl1lll@users.noreply.github.com>
2024-07-20 19:34:57 -05:00
RPRX
8deb953aec v1.8.20 2024-07-20 06:10:40 +00:00
ll11l1lIllIl1lll
a0040f13dd SplitHTTP: Server supports HTTP/3 (#3554)
Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-07-19 17:53:47 +00:00
ll11l1lIllIl1lll
d8994b7603 Fix SplitHTTP H3 crash on v2rayNG (#3559)
Fixes https://github.com/XTLS/Xray-core/issues/3556
2024-07-19 17:52:34 +00:00
RPRX
b277bacdf6 v1.8.19 2024-07-17 13:51:21 +00:00
RPRX
9288a7c0dc Upgrade dependencies 2024-07-17 13:45:16 +00:00
ll11l1lIllIl1lll
c40fc44a34 SplitHTTP: Client supports HTTP/3 (#3543)
Closes https://github.com/XTLS/Xray-core/issues/3456

Co-authored-by: Fangliding <Fangliding.fshxy@outlook.com>
Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-07-17 07:55:28 -05:00
yuhan6665
02cd3b8c74 Fix SplitHTTP race condition when creating new sessions (#3533)
Co-authored-by: nobody <nobody@nowhere.mars>
Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-07-17 11:41:17 +00:00
风扇滑翔翼
a7e198e1e2 Fix WS reading X-Forwarded-For & Add tests (#3546)
Fixes https://github.com/XTLS/Xray-core/issues/3545

---------

Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-07-17 10:40:25 +00:00
RPRX
9e6d7a3cb0 v1.8.18 2024-07-15 13:57:18 +00:00
RPRX
a4bc422ed1 README: Remove 13 inactive projects 2024-07-15 13:53:43 +00:00
abvf
59819e2a1b Fix log severity (#3535) 2024-07-15 14:04:04 +02:00
mmmray
573fb4f643 Add Windows 7 builds (#3530)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-07-15 09:53:40 +00:00
RPRX
558cfcc507 v1.8.17 2024-07-12 11:00:32 +00:00
RPRX
39675b7ef7 Upgrade github.com/xtls/reality to 20240712055506
Fixes https://github.com/XTLS/REALITY/pull/7#issuecomment-2223320694
2024-07-12 06:02:31 +00:00
MHSanaei
16de0937a8 Fix typos (#3527) 2024-07-12 00:20:06 +02:00
mmmray
c69d38ae82 add link to discussions 2024-07-11 14:48:17 -04:00
RPRX
73a001dd7a Upgrade github.com/xtls/reality to 20240711105359
Fixes https://github.com/XTLS/Xray-core/issues/3502
2024-07-11 12:02:49 +00:00
mmmray
c8f6ba9ff0 Add SplitHTTP Browser Dialer support (#3484) 2024-07-11 07:56:20 +00:00
风扇滑翔翼
308f0c64c3 Add custom Sockopt support (#3517)
* Add custom sockopt

* Add custom level

* Change field

* Sth left
2024-07-09 12:19:31 -04:00
dependabot[bot]
ce637c0c23 Bump github.com/refraction-networking/utls from 1.6.6 to 1.6.7
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.6.6 to 1.6.7.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.6.6...v1.6.7)

---
updated-dependencies:
- dependency-name: github.com/refraction-networking/utls
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-07 23:32:33 -04:00
dependabot[bot]
0d130a0489 Bump github.com/sagernet/sing-shadowsocks from 0.2.6 to 0.2.7
Bumps [github.com/sagernet/sing-shadowsocks](https://github.com/sagernet/sing-shadowsocks) from 0.2.6 to 0.2.7.
- [Commits](https://github.com/sagernet/sing-shadowsocks/compare/v0.2.6...v0.2.7)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing-shadowsocks
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-07 23:32:18 -04:00
dependabot[bot]
01a3b4912b Bump golang.org/x/net from 0.26.0 to 0.27.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.26.0 to 0.27.0.
- [Commits](https://github.com/golang/net/compare/v0.26.0...v0.27.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-07 23:32:09 -04:00
yuhan6665
b8c0768b16 Properly parse HTTP host for verification
Also fix H2 transport to not verify if host is not defined
2024-07-07 22:35:11 -04:00
yuhan6665
4c51636788 Relax server HTTP host check 2024-07-06 15:06:58 -04:00
dependabot[bot]
1113ee7fa2 Bump golang.org/x/sys from 0.21.0 to 0.22.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.21.0 to 0.22.0.
- [Commits](https://github.com/golang/sys/compare/v0.21.0...v0.22.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-06 12:21:53 -04:00
dependabot[bot]
e13f9f59da Bump google.golang.org/grpc from 1.64.0 to 1.65.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.65.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.65.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-03 16:49:38 -04:00
yuhan6665
60b2c349d2 Try to fix infinite conn read in tests 2024-07-01 23:55:30 -04:00
mmmray
c6a57b2cc1 Fix connection reuse in splithttp HTTP/1.1 (#3485) 2024-07-01 05:30:34 +02:00
yuhan6665
079d0bd8a9 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
2024-06-29 14:32:57 -04:00
RPRX
8320732743 SplitHTTP: ok -> ooooooooook (parser in client)
https://github.com/XTLS/Xray-core/pull/3479#issuecomment-2196370334
2024-06-28 16:53:18 +08:00
mmmray
c0f3bf66fd Add new header to disable HTTP middle box buffer
Co-Authored-By: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
2024-06-28 16:14:59 +08:00
maskedeken
e4f9d03bef splithttp Read() using blocking mode (#3473)
* blocking splithttp read

* Add testcase

* simplify conditions

---------

Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-06-24 11:09:24 -04:00
dependabot[bot]
7acd5a623b Bump github.com/quic-go/quic-go from 0.45.0 to 0.45.1
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.45.0 to 0.45.1.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.45.0...v0.45.1)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-23 23:18:07 -04:00
mmmray
ee2000f6e1 splithttp: Add support for H2C and http/1.1 ALPN on server (#3465)
* Add H2C support to server

* update comment

* Make http1.1 ALPN work on SplitHTTP client

Users that encounter protocol version issues will likely try to set the
ALPN explicitly. In that case we should simply grant their wish, because
the intent is obvious.
2024-06-23 13:05:37 -04:00
mmmray
74d233dd64 More docker tags 2024-06-23 12:55:37 -04:00
mmmray
eb4f9429e6 Use ArrayBuffer in WS browser dialer binaryType (#3468)
On my machine, browserdialer speedtest gives 10 Mbit/s download. Now it
can do 300 Mbit/s.
2024-06-23 05:31:57 +08:00
风扇滑翔翼
028a640b1b Update issues template 2024-06-22 12:18:25 +00:00
RPRX
9432a600e6 v1.8.16 2024-06-20 23:50:32 +00:00
mmmray
8fe976d7ee Upgrade SplitHTTP Transport (#3462)
* move to paths instead of querystrings

* permit early data on serverside

* early data for the client, fix context cancellation
2024-06-20 23:30:51 +00:00
mmmray
c1a7602412 fix compatibility issues with go 1.21 2024-06-18 10:23:29 -04:00
RPRX
404af13b56 v1.8.15 2024-06-18 05:38:04 +00:00
mmmray
c10bd28731 Add SplitHTTP Transport (#3412) 2024-06-18 05:36:36 +00:00
dependabot[bot]
501d5dec60 Bump docker/build-push-action from 5 to 6 (#3454)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-18 05:34:37 +00:00
dependabot[bot]
d04a9d4fc9 Bump github.com/gorilla/websocket from 1.5.2 to 1.5.3
Bumps [github.com/gorilla/websocket](https://github.com/gorilla/websocket) from 1.5.2 to 1.5.3.
- [Release notes](https://github.com/gorilla/websocket/releases)
- [Commits](https://github.com/gorilla/websocket/compare/v1.5.2...v1.5.3)

---
updated-dependencies:
- dependency-name: github.com/gorilla/websocket
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-16 22:58:45 -04:00
风扇滑翔翼
ae97821e40 Add regex support for domainsExcluded (#3449)
* Add regx support for domainsExcluded

* format
2024-06-16 10:51:52 -04:00
dependabot[bot]
219a7dac20 Bump github.com/miekg/dns from 1.1.59 to 1.1.61
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.59 to 1.1.61.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.59...v1.1.61)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-14 14:25:44 -04:00
dependabot[bot]
a1626cbf94 Bump github.com/cloudflare/circl from 1.3.8 to 1.3.9
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.3.8 to 1.3.9.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.3.8...v1.3.9)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-12 12:29:47 -04:00
dependabot[bot]
f7dd84d6b9 Bump google.golang.org/protobuf from 1.34.1 to 1.34.2
Bumps google.golang.org/protobuf from 1.34.1 to 1.34.2.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-12 12:29:37 -04:00
dependabot[bot]
ea02ae74ed Bump github.com/gorilla/websocket from 1.5.1 to 1.5.2
Bumps [github.com/gorilla/websocket](https://github.com/gorilla/websocket) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/gorilla/websocket/releases)
- [Commits](https://github.com/gorilla/websocket/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: github.com/gorilla/websocket
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 10:17:49 -04:00
dependabot[bot]
c15974f7ee Bump github.com/sagernet/sing from 0.4.0 to 0.4.1
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.4.0 to 0.4.1.
- [Commits](https://github.com/sagernet/sing/compare/v0.4.0...v0.4.1)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-07 10:14:22 -04:00
dependabot[bot]
13f0eccb8f Bump github.com/quic-go/quic-go from 0.44.0 to 0.45.0
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.44.0 to 0.45.0.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.44.0...v0.45.0)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-07 10:14:13 -04:00
Asen
f0cb292dc6 CI: not create zip file when not releasing
Makefile: remove unneccesary `install` target &

Add build to `.PHONY` target
2024-06-07 10:11:13 -04:00
风扇滑翔翼
3654c0d710 HTTPUpgrade send headers with specified capitalization (#3430)
* Fix HTTPUpgrade header capitalization

* Chore

* Remove excess host headers

Chore : change httpupgrade header "upgrade" to "Upgrade" #3435
2024-06-07 12:53:27 +00:00
mmmray
f8ec93dfdd drain buffer correctly in httpupgrade (#3428)
* drain buffer correctly in httpupgrade

it seems the recently added httupgrade testsuite is causing timeouts on master

i have no evidence this is the real issue, but it feels to me that the
server could accidentally over-read, and then the encapsulated
connection will block forever trying to read data

let's test it in CI a couple of times, i don't have a way to reproduce
the issue

* correctly drain buffer, again
2024-06-05 22:43:15 -04:00
mmmray
980236f2b6 preserve exact header casing when using httpupgrade (#3427)
* preserve exact header casing when using httpupgrade

* fix capitalization of websocket

* oops, we dont need net/url either

* restore old codepath when there are no headers
2024-06-05 20:43:44 -04:00
风扇滑翔翼
be29cc39d7 Add httpupgrade test 2024-06-05 17:39:55 +00:00
dependabot[bot]
9c6685d2ee Bump golang.org/x/net from 0.25.0 to 0.26.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.25.0 to 0.26.0.
- [Commits](https://github.com/golang/net/compare/v0.25.0...v0.26.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 10:36:39 -04:00
dependabot[bot]
f5a70e4200 Bump golang.org/x/crypto from 0.23.0 to 0.24.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.23.0 to 0.24.0.
- [Commits](https://github.com/golang/crypto/compare/v0.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 10:35:43 -04:00
mmmray
75b3ef71a1 fix filename 2024-06-03 16:40:13 -04:00
风扇滑翔翼
df53afceae Make ws_test uses random ports 2024-06-04 00:52:02 +08:00
AsenHu
459504300c chore: Remove unnecessary if in httpupgrade (#3413) 2024-06-04 00:13:46 +08:00
yuhan6665
075051a693 Add wireguard test 2024-06-01 19:34:31 -04:00
yuhan6665
bbf25b14d9 Update dependencies 2024-06-01 11:56:24 -04:00
isluckys
89074a14b6 Fix udp goroutine leak
v.conn.link.Reader is a pipe.Reader, doesn't implement Close(), it will fail assertion and cause the pipe to be left open
It can be fixed by using Interrupt()
2024-05-30 17:45:29 -04:00
Grvzard
73c5650b17 build: change usage of grep for better compatibility 2024-05-28 21:34:22 +08:00
yuhan6665
0a3c449cdf Inbound worker should fill context outbounds info
https://github.com/XTLS/Xray-core/issues/3388
2024-05-26 12:25:25 -04:00
RPRX
ca07a705dc Generate *.pb.go files with protoc v5.27.0
Download https://github.com/protocolbuffers/protobuf/releases/tag/v27.0
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.1
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0
(Xray-core/) go run ./infra/vprotogen
2024-05-26 03:20:53 +00:00
RPRX
3120ca4121 v1.8.13 2024-05-22 22:02:23 +00:00
yuhan6665
9b6141b83f Wireguard dial with context 2024-05-22 09:02:20 -04:00
414 changed files with 5496 additions and 3042 deletions

View File

@@ -9,6 +9,8 @@ body:
options: options:
- label: I confirm that I have read the documentation, understand the meaning of all the configuration items I wrote, and did not pile up seemingly useful options or default values. - label: I confirm that I have read the documentation, understand the meaning of all the configuration items I wrote, and did not pile up seemingly useful options or default values.
required: true required: true
- label: I provided the complete config and logs, rather than just providing the truncated parts based on my own judgment.
required: true
- label: I searched issues and did not find any similar issues. - label: I searched issues and did not find any similar issues.
required: true required: true
- type: input - type: input
@@ -40,7 +42,7 @@ body:
Don't just paste a big exported config file here. Eliminate useless inbound/outbound, rules, options, this can help determine the problem, if you really want to get help. Don't just paste a big exported config file here. Eliminate useless inbound/outbound, rules, options, this can help determine the problem, if you really want to get help.
### For logs ### For logs
Please set the log level to debug first. Please set the log level to debug and dnsLog to true first.
Restart Xray-core, then operate according to the reproduction method, try to reduce the irrelevant part in the log. Restart Xray-core, then operate according to the reproduction method, try to reduce the irrelevant part in the log.
Remember to delete parts with personal information (such as UUID and IP). Remember to delete parts with personal information (such as UUID and IP).
Provide the log of Xray-core, not the log output by the panel or other things. Provide the log of Xray-core, not the log output by the panel or other things.

View File

@@ -9,6 +9,8 @@ body:
options: options:
- label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。 - label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
required: true required: true
- label: 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。
required: true
- label: 我搜索了issues没有发现已提出的类似问题。 - label: 我搜索了issues没有发现已提出的类似问题。
required: true required: true
- type: input - type: input
@@ -40,7 +42,7 @@ body:
不要直接在这里黏贴一大段导出的 config 文件。去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。 不要直接在这里黏贴一大段导出的 config 文件。去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。
### 对于日志 ### 对于日志
请先将日志等级设置为 debug. 请先将日志等级设置为 debug, dnsLog 设置为true.
重启 Xray-core ,再按复现方式操作,尽量减少日志中的无关部分。 重启 Xray-core ,再按复现方式操作,尽量减少日志中的无关部分。
记得删除有关个人信息如UUID与IP的部分。 记得删除有关个人信息如UUID与IP的部分。
提供 Xray-core 的日志,而不是面板或者别的东西输出的日志。 提供 Xray-core 的日志,而不是面板或者别的东西输出的日志。

4
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
contact_links:
- name: Community Support and Questions
url: https://github.com/XTLS/Xray-core/discussions
about: Please ask and answer questions there. The issue tracker is for issues with core.

View File

@@ -2,21 +2,27 @@
FROM --platform=$BUILDPLATFORM golang:alpine AS build FROM --platform=$BUILDPLATFORM golang:alpine AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .
ARG TARGETOS TARGETARCH ARG TARGETOS
ARG TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
ADD https://github.com/v2fly/geoip/releases/latest/download/geoip.dat /v2fly/geoip.dat
ADD https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat /v2fly/geosite.dat
ADD https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat /loyalsoldier/geoip.dat
ADD https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat /loyalsoldier/geosite.dat
FROM --platform=${TARGETPLATFORM} alpine:latest # chainguard/static contains only tzdata and ca-certificates, can be built with multiarch static binaries.
WORKDIR /root FROM --platform=linux/amd64 chainguard/static:latest
WORKDIR /var/log/xray
COPY .github/docker/files/config.json /etc/xray/config.json COPY .github/docker/files/config.json /etc/xray/config.json
COPY --from=build /src/xray /usr/bin/xray COPY --from=build --chmod=755 /src/xray /usr/bin/xray
RUN set -ex \
&& apk add --no-cache tzdata ca-certificates \
&& mkdir -p /var/log/xray /usr/share/xray \
&& chmod +x /usr/bin/xray \
&& wget -O /usr/share/xray/geosite.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat \
&& wget -O /usr/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
USER root
WORKDIR /root
VOLUME /etc/xray VOLUME /etc/xray
ENV TZ=Asia/Shanghai ARG TZ=Asia/Shanghai
ENV TZ=$TZ
ENTRYPOINT [ "/usr/bin/xray" ] ENTRYPOINT [ "/usr/bin/xray" ]
CMD [ "-config", "/etc/xray/config.json" ] CMD [ "-config", "/etc/xray/config.json" ]
ARG flavor=v2fly
COPY --from=build /$flavor /usr/share/xray

View File

@@ -1,6 +1,8 @@
name: Build docker image name: Build docker image
on: on:
release:
types: [published]
push: push:
branches: branches:
- main - main
@@ -17,8 +19,22 @@ jobs:
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
images: ghcr.io/${{ github.repository_owner }}/xray-core images: ghcr.io/${{ github.repository_owner }}/xray-core
flavor: latest=true flavor: latest=auto
tags: | tags: |
type=sha
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
- name: Docker metadata Loyalsoldier flavor
id: loyalsoldier
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/xray-core
flavor: |
latest=auto
suffix=-ls,onlatest=true
tags: |
type=sha
type=ref,event=branch type=ref,event=branch
type=ref,event=pr type=ref,event=pr
type=semver,pattern={{version}} type=semver,pattern={{version}}
@@ -28,18 +44,33 @@ jobs:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- # Add support for more platforms with QEMU (optional)
# https://github.com/docker/setup-qemu-action
name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Build and push - name: Build and push
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
context: . context: .
platforms: linux/amd64,linux/arm64 platforms: |
linux/amd64
linux/arm64
linux/loong64
linux/riscv64
provenance: false
file: .github/docker/Dockerfile file: .github/docker/Dockerfile
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} - name: Build and push Loyalsoldier flavor
uses: docker/build-push-action@v6
with:
context: .
platforms: |
linux/amd64
linux/arm64
linux/loong64
linux/riscv64
provenance: false
file: .github/docker/Dockerfile
build-args: flavor=loyalsoldier
push: true
tags: |
${{ steps.loyalsoldier.outputs.tags }}

View File

@@ -17,14 +17,14 @@ on:
- "**/*.go" - "**/*.go"
- "go.mod" - "go.mod"
- "go.sum" - "go.sum"
- ".github/workflows/*.yml" - ".github/workflows/release.yml"
pull_request: pull_request:
types: [opened, synchronize, reopened] types: [opened, synchronize, reopened]
paths: paths:
- "**/*.go" - "**/*.go"
- "go.mod" - "go.mod"
- "go.sum" - "go.sum"
- ".github/workflows/*.yml" - ".github/workflows/release.yml"
jobs: jobs:
prepare: prepare:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -78,12 +78,15 @@ jobs:
# Include amd64 on all platforms. # Include amd64 on all platforms.
goos: [windows, freebsd, openbsd, linux, darwin] goos: [windows, freebsd, openbsd, linux, darwin]
goarch: [amd64, 386] goarch: [amd64, 386]
gotoolchain: [""]
patch-assetname: [""]
exclude: exclude:
# Exclude i386 on darwin # Exclude i386 on darwin
- goarch: 386 - goarch: 386
goos: darwin goos: darwin
include: include:
# BEIGIN MacOS ARM64 # BEGIN MacOS ARM64
- goos: darwin - goos: darwin
goarch: arm64 goarch: arm64
# END MacOS ARM64 # END MacOS ARM64
@@ -152,6 +155,16 @@ jobs:
goarch: arm goarch: arm
goarm: 7 goarm: 7
# END OPENBSD ARM # END OPENBSD ARM
# BEGIN Windows 7
- goos: windows
goarch: amd64
gotoolchain: 1.21.4
patch-assetname: win7-64
- goos: windows
goarch: 386
gotoolchain: 1.21.4
patch-assetname: win7-32
# END Windows 7
fail-fast: false fail-fast: false
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -164,16 +177,17 @@ jobs:
- name: Checkout codebase - name: Checkout codebase
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Show workflow information - name: Show workflow information
run: | run: |
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json) _NAME=${{ matrix.patch-assetname }}
[ -n "$_NAME" ] || _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME" echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version-file: go.mod go-version: ${{ matrix.gotoolchain || '1.22' }}
check-latest: true check-latest: true
- name: Get project dependencies - name: Get project dependencies
@@ -183,7 +197,7 @@ jobs:
run: | run: |
mkdir -p build_assets mkdir -p build_assets
make make
find . -maxdepth 1 -type f -regex '.*\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \; find . -maxdepth 1 -type f -regex './\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \;
- name: Restore Cache - name: Restore Cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
@@ -198,6 +212,7 @@ jobs:
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
- name: Create ZIP archive - name: Create ZIP archive
if: github.event_name == 'release'
shell: bash shell: bash
run: | run: |
pushd build_assets || exit 1 pushd build_assets || exit 1

View File

@@ -32,7 +32,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version-file: go.mod go-version: '1.22'
check-latest: true check-latest: true
- name: Restore Cache - name: Restore Cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4

View File

@@ -3,13 +3,13 @@ NAME = xray
VERSION=$(shell git describe --always --dirty) VERSION=$(shell git describe --always --dirty)
# NOTE: This MAKEFILE can be used to build Xray-core locally and in Automatic workflows. It is \ # NOTE: This MAKEFILE can be used to build Xray-core locally and in Automatic workflows. It is \
provided for convinience in automatic building and functions as a part of it. provided for convenience in automatic building and functions as a part of it.
# NOTE: If you need to modify this file, please be aware that:\ # NOTE: If you need to modify this file, please be aware that:\
- This file is not the main Makefile; it only accepts environment variables and builds the \ - This file is not the main Makefile; it only accepts environment variables and builds the \
binary.\ binary.\
- Automatic building expects the correct binaries to be built by this Makefile. If you \ - Automatic building expects the correct binaries to be built by this Makefile. If you \
intend to propose a change to this Makefile, carefully review the file below and ensure \ intend to propose a change to this Makefile, carefully review the file below and ensure \
that the change will not accidently break the automatic building:\ that the change will not accidentally break the automatic building:\
.github/workflows/release.yml \ .github/workflows/release.yml \
Otherwise it is recommended to contact the project maintainers. Otherwise it is recommended to contact the project maintainers.
@@ -23,18 +23,15 @@ ADDITION = go build -o w$(NAME).exe -trimpath -ldflags "-H windowsgui $(LDFLAGS)
else else
OUTPUT = $(NAME) OUTPUT = $(NAME)
endif endif
ifeq ($(shell echo "$(GOARCH)" | grep -Pq "(mips|mipsle)" && echo true),true) # ifeq ($(shell echo "$(GOARCH)" | grep -Eq "(mips|mipsle)" && echo true),true) #
ADDITION = GOMIPS=softfloat go build -o $(NAME)_softfloat -trimpath -ldflags "$(LDFLAGS)" -v $(MAIN) ADDITION = GOMIPS=softfloat go build -o $(NAME)_softfloat -trimpath -ldflags "$(LDFLAGS)" -v $(MAIN)
endif endif
.PHONY: clean .PHONY: clean build
build: build:
go build -o $(OUTPUT) $(PARAMS) $(MAIN) go build -o $(OUTPUT) $(PARAMS) $(MAIN)
$(ADDITION) $(ADDITION)
install:
go build -o $(PREFIX)/bin/$(OUTPUT) $(PARAMS) $(MAIN)
clean: clean:
go clean -v -i $(PWD) go clean -v -i $(PWD)
rm -f xray xray.exe wxray.exe xray_softfloat rm -f xray xray.exe wxray.exe xray_softfloat

View File

@@ -27,8 +27,7 @@
- [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**) - [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**)
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray) - [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
- Web Panel - Web Panel
- [X-UI-English](https://github.com/NidukaAkalanka/x-ui-english), [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [X-UI](https://github.com/diditra/x-ui) - [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [Xray-UI](https://github.com/qist/xray-ui)
- [Xray-UI](https://github.com/qist/xray-ui), [X-UI](https://github.com/sing-web/x-ui)
- [Hiddify](https://github.com/hiddify/hiddify-config) - [Hiddify](https://github.com/hiddify/hiddify-config)
- [Marzban](https://github.com/Gozargah/Marzban) - [Marzban](https://github.com/Gozargah/Marzban)
- [Libertea](https://github.com/VZiChoushaDui/Libertea) - [Libertea](https://github.com/VZiChoushaDui/Libertea)
@@ -67,13 +66,10 @@
- [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray)) - [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
- Windows - Windows
- [v2rayN](https://github.com/2dust/v2rayN) - [v2rayN](https://github.com/2dust/v2rayN)
- [NekoRay](https://github.com/Matsuridayo/nekoray)
- [Furious](https://github.com/LorenEteval/Furious) - [Furious](https://github.com/LorenEteval/Furious)
- [HiddifyN](https://github.com/hiddify/HiddifyN)
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient) - [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
- Android - Android
- [v2rayNG](https://github.com/2dust/v2rayNG) - [v2rayNG](https://github.com/2dust/v2rayNG)
- [HiddifyNG](https://github.com/hiddify/HiddifyNG)
- [X-flutter](https://github.com/XTLS/X-flutter) - [X-flutter](https://github.com/XTLS/X-flutter)
- iOS & macOS arm64 - iOS & macOS arm64
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [FoXray](https://apps.apple.com/app/foxray/id6448898396)
@@ -85,7 +81,6 @@
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [FoXray](https://apps.apple.com/app/foxray/id6448898396)
- Linux - Linux
- [v2rayA](https://github.com/v2rayA/v2rayA) - [v2rayA](https://github.com/v2rayA/v2rayA)
- [NekoRay](https://github.com/Matsuridayo/nekoray)
- [Furious](https://github.com/LorenEteval/Furious) - [Furious](https://github.com/LorenEteval/Furious)
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX... ## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
@@ -98,21 +93,15 @@
- [XTLS/libXray](https://github.com/XTLS/libXray) - [XTLS/libXray](https://github.com/XTLS/libXray)
- [xtlsapi](https://github.com/hiddify/xtlsapi) - [xtlsapi](https://github.com/hiddify/xtlsapi)
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite) - [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
- [XrayKit](https://github.com/arror/XrayKit)
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python) - [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
- [xray-api](https://github.com/XVGuardian/xray-api) - [xray-api](https://github.com/XVGuardian/xray-api)
- [XrayR](https://github.com/XrayR-project/XrayR) - [XrayR](https://github.com/XrayR-project/XrayR)
- [XrayR-release](https://github.com/XrayR-project/XrayR-release) - [XrayR-release](https://github.com/XrayR-project/XrayR-release)
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board) - [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
- [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta) - [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta)
- [Clash Verge](https://github.com/zzzgydi/clash-verge)
- [clashN](https://github.com/2dust/clashN) - [clashN](https://github.com/2dust/clashN)
- [Clash Meta for Android](https://github.com/MetaCubeX/ClashMetaForAndroid) - [Clash Meta for Android](https://github.com/MetaCubeX/ClashMetaForAndroid)
- [meta_for_ios](https://t.me/meta_for_ios)
- [sing-box](https://github.com/SagerNet/sing-box) - [sing-box](https://github.com/SagerNet/sing-box)
- [installReality](https://github.com/BoxXt/installReality)
- [sbox-reality](https://github.com/Misaka-blog/sbox-reality)
- [sing-box-for-ios](https://github.com/SagerNet/sing-box-for-ios)
## Contributing ## Contributing

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.28.1 // protoc-gen-go v1.34.1
// protoc v4.25.3 // protoc v5.27.0
// source: app/commander/config.proto // source: app/commander/config.proto
package commander package commander

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/dispatcher/config.proto // source: app/dispatcher/config.proto
package dispatcher package dispatcher

View File

@@ -4,11 +4,13 @@ package dispatcher
import ( import (
"context" "context"
"regexp"
"strings" "strings"
"sync" "sync"
"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"
@@ -25,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
@@ -186,8 +188,20 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
return false return false
} }
for _, d := range request.ExcludeForDomain { for _, d := range request.ExcludeForDomain {
if strings.ToLower(domain) == d { if strings.HasPrefix(d, "regexp:") {
return false pattern := d[7:]
re, err := regexp.Compile(pattern)
if err != nil {
errors.LogInfo(ctx, "Unable to compile regex")
continue
}
if re.MatchString(domain) {
return false
}
} else {
if strings.ToLower(domain) == d {
return false
}
} }
} }
protocolString := result.Protocol() protocolString := result.Protocol()
@@ -200,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 {
@@ -223,7 +237,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
outbounds = []*session.Outbound{{}} outbounds = []*session.Outbound{{}}
ctx = session.ContextWithOutbounds(ctx, outbounds) ctx = session.ContextWithOutbounds(ctx, outbounds)
} }
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
ob.OriginalTarget = destination ob.OriginalTarget = destination
ob.Target = destination ob.Target = destination
content := session.ContentFromContext(ctx) content := session.ContentFromContext(ctx)
@@ -248,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 {
@@ -273,14 +287,14 @@ 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 {
outbounds = []*session.Outbound{{}} outbounds = []*session.Outbound{{}}
ctx = session.ContextWithOutbounds(ctx, outbounds) ctx = session.ContextWithOutbounds(ctx, outbounds)
} }
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
ob.OriginalTarget = destination ob.OriginalTarget = destination
ob.Target = destination ob.Target = destination
content := session.ContentFromContext(ctx) content := session.ContentFromContext(ctx)
@@ -302,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 {
@@ -371,7 +385,7 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
} }
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) { func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() { if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() {
proxied := hosts.LookupHosts(ob.Target.String()) proxied := hosts.LookupHosts(ob.Target.String())
if proxied != nil { if proxied != nil {
@@ -394,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
@@ -407,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)
} }
} }
@@ -422,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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/dns/config.proto // source: app/dns/config.proto
package dns package dns

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/dns/fakedns/fakedns.proto // source: app/dns/fakedns/fakedns.proto
package fakedns package fakedns

View File

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

View File

@@ -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,10 +82,10 @@ 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 // Prioritize local domains with specific TLDs or those without any dot for the local DNS
if _, isLocalDNS := server.(*LocalNameServer); isLocalDNS { if _, isLocalDNS := server.(*LocalNameServer); isLocalDNS {
ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...) ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
ns.OriginalRules = append(ns.OriginalRules, localTLDsAndDotlessDomainsRule) ns.OriginalRules = append(ns.OriginalRules, localTLDsAndDotlessDomainsRule)
@@ -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
} }

View File

@@ -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
} }
@@ -258,7 +259,7 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP n
}) })
// forced to use mux for DOH // forced to use mux for DOH
// dnsCtx = session.ContextWithMuxPrefered(dnsCtx, true) // dnsCtx = session.ContextWithMuxPreferred(dnsCtx, true)
var cancel context.CancelFunc var cancel context.CancelFunc
dnsCtx, cancel = context.WithDeadline(dnsCtx, deadline) dnsCtx, cancel = context.WithDeadline(dnsCtx, deadline)
@@ -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
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/log/command/config.proto // source: app/log/command/config.proto
package command package command

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.3.0
// - protoc v4.23.1 // - protoc v5.27.0
// source: app/log/command/config.proto // source: app/log/command/config.proto
package command package command

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/log/config.proto // source: app/log/config.proto
package log package log

View File

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

View File

@@ -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"
) )
@@ -29,13 +30,13 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
} }
log.RegisterHandler(g) log.RegisterHandler(g)
// start logger instantly on inited // Start logger instantly on initialization
// other modules would log during init // Other modules would log during initialization
if err := g.startInternal(); err != nil { if err := g.startInternal(); err != nil {
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()

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/metrics/config.proto // source: app/metrics/config.proto
package metrics package metrics

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/observatory/burst/config.proto // source: app/observatory/burst/config.proto
package burst package burst

View File

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

View File

@@ -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,
@@ -208,7 +209,7 @@ func (h *HealthPing) PutResult(tag string, rtt time.Duration) {
if !ok { if !ok {
// validity is 2 times to sampling period, since the check are // validity is 2 times to sampling period, since the check are
// distributed in the time line randomly, in extreme cases, // distributed in the time line randomly, in extreme cases,
// previous checks are distributed on the left, and latters // Previous checks are distributed on the left, and later ones
// on the right // on the right
validity := h.Settings.Interval * time.Duration(h.Settings.SamplingCount) * 2 validity := h.Settings.Interval * time.Duration(h.Settings.SamplingCount) * 2
r = NewHealthPingResult(h.Settings.SamplingCount, validity) r = NewHealthPingResult(h.Settings.SamplingCount, validity)

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/observatory/command/command.proto // source: app/observatory/command/command.proto
package command package command

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.3.0
// - protoc v4.23.1 // - protoc v5.27.0
// source: app/observatory/command/command.proto // source: app/observatory/command/command.proto
package command package command

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/observatory/config.proto // source: app/observatory/config.proto
package observatory package observatory

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/policy/config.proto // source: app/policy/config.proto
package policy package policy

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/proxyman/command/command.proto // source: app/proxyman/command/command.proto
package command package command

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.3.0
// - protoc v4.23.1 // - protoc v5.27.0
// source: app/proxyman/command/command.proto // source: app/proxyman/command/command.proto
package command package command

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/proxyman/config.proto // source: app/proxyman/config.proto
package proxyman package proxyman

View File

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

View File

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

View File

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

View File

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

View File

@@ -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,14 +308,13 @@ 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{{}}
if originalDest.IsValid() { if originalDest.IsValid() {
outbounds := []*session.Outbound{{ outbounds[0].Target = originalDest
Target: originalDest,
}}
ctx = session.ContextWithOutbounds(ctx, outbounds)
} }
ctx = session.ContextWithOutbounds(ctx, outbounds)
ctx = session.ContextWithInbound(ctx, &session.Inbound{ ctx = session.ContextWithInbound(ctx, &session.Inbound{
Source: source, Source: source,
Gateway: net.UDPDestination(w.address, w.port), Gateway: net.UDPDestination(w.address, w.port),
@@ -328,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
@@ -359,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 {
@@ -403,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
} }
@@ -453,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{
@@ -480,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")
} }
} }
@@ -502,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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/reverse/config.proto // source: app/reverse/config.proto
package reverse package reverse

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/router/command/command.proto // source: app/router/command/command.proto
package command package command

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.3.0
// - protoc v4.23.1 // - protoc v5.27.0
// source: app/router/command/command.proto // source: app/router/command/command.proto
package command package command

View File

@@ -272,7 +272,7 @@ func TestServiceSubscribeSubsetOfFields(t *testing.T) {
} }
} }
func TestSerivceTestRoute(t *testing.T) { func TestServiceTestRoute(t *testing.T) {
c := stats.NewChannel(&stats.ChannelConfig{ c := stats.NewChannel(&stats.ChannelConfig{
SubscriberLimit: 1, SubscriberLimit: 1,
BufferSize: 16, BufferSize: 16,

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/router/config.proto // source: app/router/config.proto
package router package router

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -95,7 +95,7 @@ func TestStatsChannel(t *testing.T) {
} }
} }
func TestStatsChannelUnsubcribe(t *testing.T) { func TestStatsChannelUnsubscribe(t *testing.T) {
c := NewChannel(&ChannelConfig{Blocking: true}) c := NewChannel(&ChannelConfig{Blocking: true})
common.Must(c.Start()) common.Must(c.Start())
defer c.Close() defer c.Close()

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/stats/command/command.proto // source: app/stats/command/command.proto
package command package command

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.3.0
// - protoc v4.23.1 // - protoc v5.27.0
// source: app/stats/command/command.proto // source: app/stats/command/command.proto
package command package command

View File

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

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.23.1 // protoc v5.27.0
// source: app/stats/config.proto // source: app/stats/config.proto
package stats package stats

View File

@@ -18,7 +18,7 @@ func TestStatsCounter(t *testing.T) {
common.Must(err) common.Must(err)
if v := c.Add(1); v != 1 { if v := c.Add(1); v != 1 {
t.Fatal("unpexcted Add(1) return: ", v, ", wanted ", 1) t.Fatal("unexpected Add(1) return: ", v, ", wanted ", 1)
} }
if v := c.Set(0); v != 1 { if v := c.Set(0); v != 1 {

View File

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

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