Compare commits

...

75 Commits

Author SHA1 Message Date
RPRX
4be32e99b2 v24.12.31
XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
2024-12-31 12:12:03 +00:00
RPRX
5af90684c4 Inbounds config: Add mixed as an alias of socks
https://github.com/XTLS/Xray-core/pull/3682#issuecomment-2292600144
2024-12-31 11:55:16 +00:00
RPRX
369d8944cf Sockopt config: Add penetrate for XHTTP U-D-S, Remove tcpNoDelay
Now `sockopt` can be shared via `extra`, and be replaced with upload's forcibly.

Closes https://github.com/XTLS/Xray-core/issues/4227
2024-12-31 11:10:17 +00:00
RPRX
4ce65fc74c XHTTP XMUX: cMaxLifetimeMs -> hMaxReusableSecs, Refactor default values
"xmux": {
    "maxConcurrency": "16-32",
    "maxConnections": 0,
    "cMaxReuseTimes": 0,
    "hMaxRequestTimes": "600-900",
    "hMaxReusableSecs": "1800-3000",
    "hKeepAlivePeriod": 0
}

Fixes https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11685057
2024-12-31 10:00:19 +00:00
RPRX
93f72db9fd v24.12.28
XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
2024-12-28 13:57:23 +00:00
RPRX
ff4331a7a8 XHTTP XMUX: Increase the default value for cMaxReuseTimes
"64-128" -> "256-512"
2024-12-28 08:20:59 +00:00
RPRX
a8559a1b46 Dokodemo TPROXY: Interrupt UDP download if upload timeouts
https://github.com/XTLS/Xray-core/issues/4194#issuecomment-2564156340

Fixes https://github.com/XTLS/Xray-core/issues/4194
2024-12-28 04:06:49 +00:00
yuhan6665
42aea01fb5 Core: Add mutex to injection resolution (#4206)
* Revert "Add RequireFeaturesAsync() that works regardless order of app init"

* Add mutex to injection resolution

- Turns out we already support async DI resolution regardless of feature ordering
Previous code contain a race condition causing some resolution is lost
- Note that the new mutex cover s.pendingResolutions and s.features
but must not cover callbackResolution() due to deadlock
- Refactor some method names and simplify code

* Add OptionalFeatures injection

For example OptionalFeatures() is useful for fakedns module
2024-12-26 12:55:12 +00:00
dependabot[bot]
a7909f8671 Bump google.golang.org/protobuf from 1.36.0 to 1.36.1 (#4203)
Bumps google.golang.org/protobuf from 1.36.0 to 1.36.1.

---
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-24 13:03:17 +00:00
leo
b287d6419b chore: use errors.New to replace fmt.Errorf with no parameters (#4204)
Signed-off-by: RiceChuan <lc582041246@gmail.com>
2024-12-24 00:17:00 -05:00
dependabot[bot]
d54d20abea Bump golang.org/x/net from 0.32.0 to 0.33.0 (#4182)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.32.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.32.0...v0.33.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-22 09:21:06 +00:00
maoxikun
868799ef04 DNS: Always use a DNS Message ID of 0 for DoH and DoQ (#4193)
Co-authored-by: dyhkwong <50692134+dyhkwong@users.noreply.github.com>
2024-12-22 09:19:09 +00:00
RPRX
db934f0832 XHTTP client: Merge Open* into OpenStream(), and more
https://github.com/XTLS/Xray-core/issues/4148#issuecomment-2557066988
2024-12-20 14:35:33 +00:00
RPRX
53b04d560b XHTTP client: Make H3 httptrace work on v2rayNG
Introduced in https://github.com/XTLS/Xray-core/pull/4150
2024-12-20 07:19:41 +00:00
RPRX
1410b6335b XHTTP XMUX: Fix OpenUsage never gets reduced
Introduced in https://github.com/XTLS/Xray-core/pull/4163
2024-12-20 06:19:10 +00:00
RPRX
cab2fdefd3 v24.12.18
XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
2024-12-18 13:39:35 +00:00
RPRX
ff8b66aacb XHTTP client: scMaxEachPostBytes should be bigger than buf.Size (8192)
To avoid no size limit.
2024-12-18 13:25:34 +00:00
dependabot[bot]
15318976f6 Bump google.golang.org/protobuf from 1.35.2 to 1.36.0 (#4175)
Bumps google.golang.org/protobuf from 1.35.2 to 1.36.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-18 11:43:48 +00:00
dependabot[bot]
a168f5360e Bump golang.org/x/crypto from 0.30.0 to 0.31.0 (#4156)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.30.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.30.0...v0.31.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-18 11:32:11 +00:00
RPRX
9dbdf92c27 XHTTP downloadSettings: Inherit sockopt if its own doesn't exist (e.g., in extra)
If you want `downloadSettings` to use its own `sockopt`, make sure that `extra` doesn't exist.
2024-12-18 11:22:29 +00:00
RPRX
96fb680d45 REALITY, TLS config: Set "chrome" as the default fingerprint
Other VLESS implementations should follow this change.
2024-12-17 11:02:51 +00:00
珐琅彩山水佩奇童车游春马蹄杯
5836afc41f WebSocket config: Fix headers (#4177)
Fixes https://github.com/XTLS/Xray-core/issues/4176
2024-12-17 08:53:16 +00:00
RPRX
7d0a80b501 v24.12.15 2024-12-15 12:36:19 +00:00
RPRX
73e0d4a666 XHTTP XMUX: Add hMaxRequestTimes and hKeepAlivePeriod (#4163)
Fixes https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11492833
2024-12-15 05:43:10 +00:00
RPRX
7463561856 XHTTP client: Add decideHTTPVersion() and more logs
https://github.com/XTLS/Xray-core/pull/4150#issuecomment-2537981368
2024-12-12 12:19:18 +00:00
RPRX
743435d6e6 Core: Fix startup error when dns exists but fakedns doesn't
Fixes https://github.com/XTLS/Xray-core/issues/4155
2024-12-12 06:56:05 +00:00
RPRX
8cd9a74376 XHTTP client: Refactor "packet-up" mode, chasing "stream-up" (#4150)
* Add wroteRequest (waiting for new quic-go)

* Use XTLS/quic-go instead

* Client doesn't need `scMaxConcurrentPosts` anymore

* GotConn is available in H3

* `scMaxConcurrentPosts` -> `scMaxBufferedPosts` (server only, 30 by default)

Fixes https://github.com/XTLS/Xray-core/issues/4100
2024-12-11 14:05:39 +00:00
Andi
6be3c35db8 Chore: "io/ioutil" -> "io" (#4143)
Signed-off-by: ChengenH <hce19970702@gmail.com>
2024-12-11 02:02:23 +00:00
yuhan6665
0e2304c403 Core: Fix memory leaks with RequireFeatures() (#4095)
Fixes https://github.com/XTLS/Xray-core/issues/4054
Fixes https://github.com/XTLS/Xray-core/issues/3338
Fixes https://github.com/XTLS/Xray-core/issues/3221
2024-12-11 01:07:52 +00:00
RPRX
a2b773135a XHTTP, WS, HU: Forbid "host" in headers, read serverName instead (#4142)
WebSocket's config files should be updated ASAP.
2024-12-11 00:58:14 +00:00
RPRX
9cb6816383 README.md: Update Donation & NFTs 2024-12-07 14:43:38 +00:00
RPRX
46d8d9ef02 XHTTP server: Forbid Mux.Cool except pure XUDP (#4128)
https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11491701
2024-12-07 04:45:45 +00:00
dependabot[bot]
34141c940e Bump golang.org/x/net from 0.31.0 to 0.32.0 (#4110)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.31.0 to 0.32.0.
- [Commits](https://github.com/golang/net/compare/v0.31.0...v0.32.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-06 23:55:10 +00:00
风扇滑翔翼
3e7002d24c WireGuard inbound: Add missing inbound session information back (#4126)
Fixes https://github.com/XTLS/Xray-core/issues/4121
2024-12-06 23:50:26 +00:00
RPRX
ae62a0fb52 Transport: Remove HTTP
Migrated to XHTTP "stream-one" mode.
2024-12-02 09:56:16 +00:00
RPRX
98a72b6fb4 v24.11.30
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2024-11-30 04:16:35 +00:00
hr567
4f6f12616c WebSocket config: Add heartbeatPeriod for client & server (#4065)
https://github.com/XTLS/Xray-core/pull/4065#issuecomment-2502627154

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-29 02:08:08 +00:00
风扇滑翔翼
c87cf8ff52 XHTTP config: Add keepAlivePeriod for client (#4075)
Closes https://github.com/XTLS/Xray-core/issues/4053

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-29 02:05:11 +00:00
RPRX
f7bd98b13c XHTTP: Add "stream-one" mode for client & server (#4071)
""Breaking"": Client uses "stream-one" mode by default when using **REALITY** ("stream-up" if "downloadSettings" exists)
2024-11-27 20:19:18 +00:00
Aleksandr
d8934cf839 Chore: Improved log messaging (#4050)
* update log messages

* Update inbound.go
2024-11-25 11:16:29 -05:00
zonescape
ce8c415d43 Test: Remove temporary directory afterwards (#4045) 2024-11-24 23:00:00 -05:00
zonescape
034a485afe Chore: Refactor tests in app/router (#4019) 2024-11-24 22:53:31 -05:00
dependabot[bot]
384d07999c Bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#4060)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-24 22:37:28 -05:00
RPRX
513f18bf53 v24.11.21 2024-11-21 05:47:07 +00:00
RPRX
817fa72874 XHTTP client: Add gRPC header to "stream-up" mode by default (#4042)
""Breaking"": Client uses "stream-up" mode by default when using **TLS H2** or REALITY
2024-11-21 05:45:49 +00:00
风扇滑翔翼
0a252ac15d HTTP transport: Use dest as Host if not set (#4038) 2024-11-21 05:42:19 +00:00
zonescape
6ba0dbafd7 Test: Delete temporary file afterwards (#4028) 2024-11-20 05:03:39 +00:00
风扇滑翔翼
59e5d24280 WireGuard inbound: Fix leaking session information between requests (#4030)
Fixes https://github.com/XTLS/Xray-core/issues/3948 https://github.com/XTLS/Xray-core/issues/4025
2024-11-20 05:00:40 +00:00
dependabot[bot]
7d3d6b05e3 Bump github.com/sagernet/sing from 0.5.0 to 0.5.1 (#4026)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.5.0 to 0.5.1.
- [Commits](https://github.com/sagernet/sing/compare/v0.5.0...v0.5.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-19 03:19:34 +00:00
yiguous
55e045d098 Config: Correctly marshal Address to JSON (#4021) 2024-11-19 03:18:47 +00:00
dependabot[bot]
5a96ef632d Bump google.golang.org/protobuf from 1.35.1 to 1.35.2 (#4018)
Bumps google.golang.org/protobuf from 1.35.1 to 1.35.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 05:08:03 +00:00
RPRX
1f570d9cef XHTTP test: Fix Test_maxUpload
https://github.com/XTLS/Xray-core/pull/3260#issuecomment-2481946715
2024-11-18 04:53:21 +00:00
RPRX
2d7b0e8cd4 XHTTP client: Fix upload issue in "packet-up" mode inherited from SplitHTTP
Fixes https://github.com/XTLS/Xray-core/issues/3972
2024-11-17 06:03:25 +00:00
zonescape
ec1fd008c4 Chore: Refactor infra/conf.TestToCidrList() (#4017) 2024-11-14 11:04:17 -05:00
风扇滑翔翼
17825b25f2 WireGuard kernelTun: Fix multi-outbounds not work (#4015)
Fixes https://github.com/XTLS/Xray-core/issues/2817
2024-11-14 00:13:27 +00:00
zonescape
83ae38497b Chore: Drop dead code in test (#4012) 2024-11-13 10:41:54 -05:00
pinglanlu
7b4a686b74 Chore: Use a more direct and less error-prone return value (#4008)
Signed-off-by: pinglanlu <pinglanlu@outlook.com>
2024-11-12 10:44:41 -05:00
lxsq
48ac662298 Update Dockerfile to Use Multiple Config Files (#4010) 2024-11-12 10:41:42 -05:00
RPRX
1a238cbb7d REALITY client: Log invalid connections at warning level
Closes https://github.com/XTLS/Xray-core/issues/4001
2024-11-12 06:42:52 +00:00
zonescape
44b1dd0e67 Test: Change address for DNS over QUIC tests (#4002)
dns.adguard.com can be blocked in some places
2024-11-11 14:43:57 -05:00
RPRX
0df2446f82 v24.11.11 2024-11-11 04:22:33 +00:00
dependabot[bot]
85b3c2328f Bump golang.org/x/net from 0.30.0 to 0.31.0 (#3999)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.30.0 to 0.31.0.
- [Commits](https://github.com/golang/net/compare/v0.30.0...v0.31.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 04:21:50 +00:00
风扇滑翔翼
571777483b TLS: Add CurvePreferences (to enable kyber768) (#3991)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-11 04:21:28 +00:00
风扇滑翔翼
1ffb8a92cd Sniff: Prevent crash on QUIC sniffer panic (#3978)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-11 04:20:54 +00:00
RPRX
480748403a Chore: Fix versions in some *.pb.go files
47fad1fbfd
2024-11-11 03:27:30 +00:00
RPRX
bd0841a75b XHTTP config: Add "extra" for sharing extra fields (#4000) 2024-11-11 02:50:39 +00:00
zonescape
83bab5dd90 Chore: Run gofmt (#3990) 2024-11-09 11:16:11 +00:00
RPRX
bc4bf3d38f XHTTP: Add "stream-up" mode for client & server (#3994) 2024-11-09 11:05:41 +00:00
dependabot[bot]
94c02f090e Bump golang.org/x/sys from 0.26.0 to 0.27.0 (#3987)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.26.0 to 0.27.0.
- [Commits](https://github.com/golang/sys/compare/v0.26.0...v0.27.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 10:29:50 -05:00
dependabot[bot]
5af750b336 Bump golang.org/x/crypto from 0.28.0 to 0.29.0 (#3986)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.28.0 to 0.29.0.
- [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.29.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 10:29:35 -05:00
dependabot[bot]
6cb58d9315 Bump golang.org/x/sync from 0.8.0 to 0.9.0 (#3985)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.8.0 to 0.9.0.
- [Commits](https://github.com/golang/sync/compare/v0.8.0...v0.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 10:25:47 -05:00
dependabot[bot]
8cd3f5448d Bump github.com/sagernet/sing from 0.4.3 to 0.5.0 (#3971)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.4.3 to 0.5.0.
- [Commits](https://github.com/sagernet/sing/compare/v0.4.3...v0.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 10:25:09 -05:00
zonescape
b98f29bf3e Chore: Fix some comments (#3979) 2024-11-07 11:00:04 -05:00
RPRX
6877ca5201 XHTTP client: Allow different paths in U-D-S (#3977) 2024-11-07 03:50:28 +00:00
zonescape
71cfea8aae Chore: Fix some spelling errors (#3976) 2024-11-06 10:42:43 -05:00
139 changed files with 2002 additions and 2900 deletions

View File

@@ -22,7 +22,7 @@ VOLUME /etc/xray
ARG TZ=Asia/Shanghai ARG TZ=Asia/Shanghai
ENV TZ=$TZ ENV TZ=$TZ
ENTRYPOINT [ "/usr/bin/xray" ] ENTRYPOINT [ "/usr/bin/xray" ]
CMD [ "-config", "/etc/xray/config.json" ] CMD [ "-confdir", "/etc/xray/" ]
ARG flavor=v2fly ARG flavor=v2fly
COPY --from=build --chmod=644 /$flavor /usr/share/xray COPY --from=build --chmod=644 /$flavor /usr/share/xray

View File

@@ -6,7 +6,9 @@
## Donation & NFTs ## Donation & NFTs
[Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633) - **ETH/USDT/USDC: `0xDc3Fe44F0f25D13CACb1C4896CD0D321df3146Ee`**
- **Project X NFT: [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633)**
- **REALITY NFT: [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113)**
## License ## License

View File

@@ -106,7 +106,7 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
d := new(DefaultDispatcher) d := new(DefaultDispatcher)
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error { if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
d.fdns = fdns d.fdns = fdns
}) })
return d.Init(config.(*Config), om, router, pm, sm, dc) return d.Init(config.(*Config), om, router, pm, sm, dc)

View File

@@ -28,7 +28,7 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
} }
return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) { return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
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 != "" {

View File

@@ -35,7 +35,7 @@ type Client struct {
var errExpectedIPNonMatch = errors.New("expectIPs not match") var errExpectedIPNonMatch = errors.New("expectIPs not match")
// NewServer creates a name server object according to the network destination url. // NewServer creates a name server object according to the network destination url.
func NewServer(dest net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (Server, error) { func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (Server, error) {
if address := dest.Address; address.Family().IsDomain() { if address := dest.Address; address.Family().IsDomain() {
u, err := url.Parse(address.Domain()) u, err := url.Parse(address.Domain())
if err != nil { if err != nil {
@@ -55,7 +55,11 @@ func NewServer(dest net.Destination, dispatcher routing.Dispatcher, queryStrateg
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
return NewTCPLocalNameServer(u, queryStrategy) return NewTCPLocalNameServer(u, queryStrategy)
case strings.EqualFold(u.String(), "fakedns"): case strings.EqualFold(u.String(), "fakedns"):
return NewFakeDNSServer(), nil var fd dns.FakeDNSEngine
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
fd = fdns
})
return NewFakeDNSServer(fd), nil
} }
} }
if dest.Network == net.Network_Unknown { if dest.Network == net.Network_Unknown {
@@ -80,7 +84,7 @@ func NewClient(
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
// 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(ctx, ns.Address.AsDestination(), dispatcher, ns.GetQueryStrategy())
if err != nil { if err != nil {
return errors.New("failed to create nameserver").Base(err).AtWarning() return errors.New("failed to create nameserver").Base(err).AtWarning()
} }

View File

@@ -8,7 +8,6 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -35,7 +34,6 @@ type DoHNameServer struct {
ips map[string]*record ips map[string]*record
pub *pubsub.Service pub *pubsub.Service
cleanup *task.Periodic cleanup *task.Periodic
reqID uint32
httpClient *http.Client httpClient *http.Client
dohURL string dohURL string
name string name string
@@ -222,7 +220,7 @@ func (s *DoHNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
} }
func (s *DoHNameServer) newReqID() uint16 { func (s *DoHNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1)) return 0
} }
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) {

View File

@@ -5,7 +5,6 @@ import (
"github.com/xtls/xray-core/common/errors" "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/features/dns" "github.com/xtls/xray-core/features/dns"
) )
@@ -13,8 +12,8 @@ type FakeDNSServer struct {
fakeDNSEngine dns.FakeDNSEngine fakeDNSEngine dns.FakeDNSEngine
} }
func NewFakeDNSServer() *FakeDNSServer { func NewFakeDNSServer(fd dns.FakeDNSEngine) *FakeDNSServer {
return &FakeDNSServer{} return &FakeDNSServer{fakeDNSEngine: fd}
} }
func (FakeDNSServer) Name() string { func (FakeDNSServer) Name() string {
@@ -23,12 +22,9 @@ func (FakeDNSServer) Name() string {
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, opt dns.IPOption, _ bool) ([]net.IP, error) { func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, opt dns.IPOption, _ bool) ([]net.IP, error) {
if f.fakeDNSEngine == nil { if f.fakeDNSEngine == nil {
if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) { return nil, errors.New("Unable to locate a fake DNS Engine").AtError()
f.fakeDNSEngine = fd
}); err != nil {
return nil, errors.New("Unable to locate a fake DNS Engine").Base(err).AtError()
}
} }
var ips []net.Address var ips []net.Address
if fkr0, ok := f.fakeDNSEngine.(dns.FakeDNSEngineRev0); ok { if fkr0, ok := f.fakeDNSEngine.(dns.FakeDNSEngineRev0); ok {
ips = fkr0.GetFakeIPForDomain3(domain, opt.IPv4Enable, opt.IPv6Enable) ips = fkr0.GetFakeIPForDomain3(domain, opt.IPv4Enable, opt.IPv6Enable)

View File

@@ -6,10 +6,9 @@ import (
"encoding/binary" "encoding/binary"
"net/url" "net/url"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/quic-go/quic-go" "github.com/xtls/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/errors"
@@ -37,7 +36,6 @@ type QUICNameServer struct {
ips map[string]*record ips map[string]*record
pub *pubsub.Service pub *pubsub.Service
cleanup *task.Periodic cleanup *task.Periodic
reqID uint32
name string name string
destination *net.Destination destination *net.Destination
connection quic.Connection connection quic.Connection
@@ -156,7 +154,7 @@ func (s *QUICNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
} }
func (s *QUICNameServer) newReqID() uint16 { func (s *QUICNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1)) return 0
} }
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) {

View File

@@ -14,7 +14,7 @@ import (
) )
func TestQUICNameServer(t *testing.T) { func TestQUICNameServer(t *testing.T) {
url, err := url.Parse("quic://dns.adguard.com") url, err := url.Parse("quic://dns.adguard-dns.com")
common.Must(err) common.Must(err)
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP) s, err := NewQUICNameServer(url, QueryStrategy_USE_IP)
common.Must(err) common.Must(err)
@@ -42,7 +42,7 @@ func TestQUICNameServer(t *testing.T) {
} }
func TestQUICNameServerWithIPv4Override(t *testing.T) { func TestQUICNameServerWithIPv4Override(t *testing.T) {
url, err := url.Parse("quic://dns.adguard.com") url, err := url.Parse("quic://dns.adguard-dns.com")
common.Must(err) common.Must(err)
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP4) s, err := NewQUICNameServer(url, QueryStrategy_USE_IP4)
common.Must(err) common.Must(err)
@@ -65,7 +65,7 @@ func TestQUICNameServerWithIPv4Override(t *testing.T) {
} }
func TestQUICNameServerWithIPv6Override(t *testing.T) { func TestQUICNameServerWithIPv6Override(t *testing.T) {
url, err := url.Parse("quic://dns.adguard.com") url, err := url.Parse("quic://dns.adguard-dns.com")
common.Must(err) common.Must(err)
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP6) s, err := NewQUICNameServer(url, QueryStrategy_USE_IP6)
common.Must(err) common.Must(err)

View File

@@ -31,8 +31,8 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
} }
log.RegisterHandler(g) log.RegisterHandler(g)
// Start logger instantly on initialization // start logger now,
// Other modules would log during initialization // then other modules will be able to log during initialization
if err := g.startInternal(); err != nil { if err := g.startInternal(); err != nil {
return nil, err return nil, err
} }

View File

@@ -12,6 +12,7 @@ import (
"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"
"github.com/xtls/xray-core/features/routing"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -88,13 +89,15 @@ func (o *Observer) Close() error {
func New(ctx context.Context, config *Config) (*Observer, error) { func New(ctx context.Context, config *Config) (*Observer, error) {
var outboundManager outbound.Manager var outboundManager outbound.Manager
err := core.RequireFeatures(ctx, func(om outbound.Manager) { var dispatcher routing.Dispatcher
err := core.RequireFeatures(ctx, func(om outbound.Manager, rd routing.Dispatcher) {
outboundManager = om outboundManager = om
dispatcher = rd
}) })
if err != nil { if err != nil {
return nil, errors.New("Cannot get depended features").Base(err) return nil, errors.New("Cannot get depended features").Base(err)
} }
hp := NewHealthPing(ctx, config.PingConfig) hp := NewHealthPing(ctx, dispatcher, config.PingConfig)
return &Observer{ return &Observer{
config: config, config: config,
ctx: ctx, ctx: ctx,

View File

@@ -9,6 +9,7 @@ import (
"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/errors"
"github.com/xtls/xray-core/features/routing"
) )
// HealthPingSettings holds settings for health Checker // HealthPingSettings holds settings for health Checker
@@ -23,6 +24,7 @@ type HealthPingSettings struct {
// HealthPing is the health checker for balancers // HealthPing is the health checker for balancers
type HealthPing struct { type HealthPing struct {
ctx context.Context ctx context.Context
dispatcher routing.Dispatcher
access sync.Mutex access sync.Mutex
ticker *time.Ticker ticker *time.Ticker
tickerClose chan struct{} tickerClose chan struct{}
@@ -32,7 +34,7 @@ type HealthPing struct {
} }
// NewHealthPing creates a new HealthPing with settings // NewHealthPing creates a new HealthPing with settings
func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing { func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *HealthPingConfig) *HealthPing {
settings := &HealthPingSettings{} settings := &HealthPingSettings{}
if config != nil { if config != nil {
settings = &HealthPingSettings{ settings = &HealthPingSettings{
@@ -65,6 +67,7 @@ func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing {
} }
return &HealthPing{ return &HealthPing{
ctx: ctx, ctx: ctx,
dispatcher: dispatcher,
Settings: settings, Settings: settings,
Results: nil, Results: nil,
} }
@@ -149,6 +152,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
handler := tag handler := tag
client := newPingClient( client := newPingClient(
h.ctx, h.ctx,
h.dispatcher,
h.Settings.Destination, h.Settings.Destination,
h.Settings.Timeout, h.Settings.Timeout,
handler, handler,

View File

@@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/tagged" "github.com/xtls/xray-core/transport/internet/tagged"
) )
@@ -14,10 +15,10 @@ type pingClient struct {
httpClient *http.Client httpClient *http.Client
} }
func newPingClient(ctx context.Context, destination string, timeout time.Duration, handler string) *pingClient { func newPingClient(ctx context.Context, dispatcher routing.Dispatcher, destination string, timeout time.Duration, handler string) *pingClient {
return &pingClient{ return &pingClient{
destination: destination, destination: destination,
httpClient: newHTTPClient(ctx, handler, timeout), httpClient: newHTTPClient(ctx, dispatcher, handler, timeout),
} }
} }
@@ -28,7 +29,7 @@ func newDirectPingClient(destination string, timeout time.Duration) *pingClient
} }
} }
func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration) *http.Client { func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, handler string, timeout time.Duration) *http.Client {
tr := &http.Transport{ tr := &http.Transport{
DisableKeepAlives: true, DisableKeepAlives: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
@@ -36,7 +37,7 @@ func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return tagged.Dialer(ctxv, dest, handler) return tagged.Dialer(ctxv, dispatcher, dest, handler)
}, },
} }
return &http.Client{ return &http.Client{
@@ -52,7 +53,7 @@ func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration)
// MeasureDelay returns the delay time of the request to dest // MeasureDelay returns the delay time of the request to dest
func (s *pingClient) MeasureDelay() (time.Duration, error) { func (s *pingClient) MeasureDelay() (time.Duration, error) {
if s.httpClient == nil { if s.httpClient == nil {
panic("pingClient no initialized") panic("pingClient not initialized")
} }
req, err := http.NewRequest(http.MethodHead, s.destination, nil) req, err := http.NewRequest(http.MethodHead, s.destination, nil)
if err != nil { if err != nil {

View File

@@ -38,7 +38,7 @@ func init() {
sv := &service{v: s} sv := &service{v: s}
err := s.RequireFeatures(func(Observatory extension.Observatory) { err := s.RequireFeatures(func(Observatory extension.Observatory) {
sv.observatory = Observatory sv.observatory = Observatory
}) }, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -18,6 +18,7 @@ import (
"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"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/tagged" "github.com/xtls/xray-core/transport/internet/tagged"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -32,6 +33,7 @@ type Observer struct {
finished *done.Instance finished *done.Instance
ohm outbound.Manager ohm outbound.Manager
dispatcher routing.Dispatcher
} }
func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) { func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) {
@@ -131,7 +133,7 @@ func (o *Observer) probe(outbound string) ProbeResult {
return errors.New("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, o.dispatcher, dest, outbound)
if err != nil { if err != nil {
return errors.New("cannot dial remote address ", dest).Base(err) return errors.New("cannot dial remote address ", dest).Base(err)
} }
@@ -215,8 +217,10 @@ func (o *Observer) findStatusLocationLockHolderOnly(outbound string) int {
func New(ctx context.Context, config *Config) (*Observer, error) { func New(ctx context.Context, config *Config) (*Observer, error) {
var outboundManager outbound.Manager var outboundManager outbound.Manager
err := core.RequireFeatures(ctx, func(om outbound.Manager) { var dispatcher routing.Dispatcher
err := core.RequireFeatures(ctx, func(om outbound.Manager, rd routing.Dispatcher) {
outboundManager = om outboundManager = om
dispatcher = rd
}) })
if err != nil { if err != nil {
return nil, errors.New("Cannot get depended features").Base(err) return nil, errors.New("Cannot get depended features").Base(err)
@@ -225,6 +229,7 @@ func New(ctx context.Context, config *Config) (*Observer, error) {
config: config, config: config,
ctx: ctx, ctx: ctx,
ohm: outboundManager, ohm: outboundManager,
dispatcher: dispatcher,
}, nil }, 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.34.2 // protoc-gen-go v1.35.1
// protoc v4.25.3 // protoc v5.28.2
// source: app/policy/config.proto // source: app/policy/config.proto
package policy package policy
@@ -599,104 +599,6 @@ func file_app_policy_config_proto_init() {
if File_app_policy_config_proto != nil { if File_app_policy_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_policy_config_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Second); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*Policy); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*SystemPolicy); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*Policy_Timeout); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*Policy_Stats); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*Policy_Buffer); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*SystemPolicy_Stats); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -177,7 +177,7 @@ func (s *service) Register(server *grpc.Server) {
common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) { common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) {
hs.ihm = im hs.ihm = im
hs.ohm = om hs.ohm = om
})) }, false))
RegisterHandlerServiceServer(server, hs) RegisterHandlerServiceServer(server, hs)
// For compatibility purposes // For compatibility purposes

View File

@@ -7,13 +7,14 @@ 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/errors"
"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"
"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"
) )
// Manager is to manage all inbound handlers. // Manager manages all inbound handlers.
type Manager struct { type Manager struct {
access sync.RWMutex access sync.RWMutex
untaggedHandler []inbound.Handler untaggedHandler []inbound.Handler
@@ -158,6 +159,9 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
Mark: streamSettings.SocketSettings.Mark, Mark: streamSettings.SocketSettings.Mark,
}) })
} }
if streamSettings != nil && streamSettings.ProtocolName == "splithttp" {
ctx = session.ContextWithAllowedNetwork(ctx, net.Network_UDP)
}
allocStrategy := receiverSettings.AllocationStrategy allocStrategy := receiverSettings.AllocationStrategy
if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always { if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always {

View File

@@ -11,8 +11,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/errors"
"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/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
@@ -54,7 +54,7 @@ func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter)
return uplinkCounter, downlinkCounter return uplinkCounter, downlinkCounter
} }
// Handler is an implements of outbound.Handler. // Handler implements outbound.Handler.
type Handler struct { type Handler struct {
tag string tag string
senderSettings *proxyman.SenderConfig senderSettings *proxyman.SenderConfig

View File

@@ -31,6 +31,12 @@ type RoundRobinStrategy struct {
func (s *RoundRobinStrategy) InjectContext(ctx context.Context) { func (s *RoundRobinStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx s.ctx = ctx
if len(s.FallbackTag) > 0 {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
} }
func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string { func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string {
@@ -38,12 +44,6 @@ func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string {
} }
func (s *RoundRobinStrategy) PickOutbound(tags []string) string { func (s *RoundRobinStrategy) PickOutbound(tags []string) string {
if len(s.FallbackTag) > 0 && s.observatory == nil {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
if s.observatory != nil { if s.observatory != nil {
observeReport, err := s.observatory.GetObservation(s.ctx) observeReport, err := s.observatory.GetObservation(s.ctx)
if err == nil { if err == nil {

View File

@@ -135,7 +135,7 @@ func (s *service) Register(server *grpc.Server) {
vCoreDesc := RoutingService_ServiceDesc vCoreDesc := RoutingService_ServiceDesc
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService" vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
server.RegisterService(&vCoreDesc, rs) server.RegisterService(&vCoreDesc, rs)
})) }, false))
} }
func init() { func init() {

View File

@@ -1,6 +1,7 @@
package router_test package router_test
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@@ -13,16 +14,25 @@ import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
func init() { func getAssetPath(file string) (string, error) {
wd, err := os.Getwd() path := platform.GetAssetLocation(file)
common.Must(err) _, err := os.Stat(path)
if os.IsNotExist(err) {
path := filepath.Join("..", "..", "resources", file)
_, err := os.Stat(path)
if os.IsNotExist(err) {
return "", fmt.Errorf("can't find %s in standard asset locations or {project_root}/resources", file)
}
if err != nil {
return "", fmt.Errorf("can't stat %s: %v", path, err)
}
return path, nil
}
if err != nil {
return "", fmt.Errorf("can't stat %s: %v", path, err)
}
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) { return path, nil
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
}
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat")))
}
} }
func TestGeoIPMatcherContainer(t *testing.T) { func TestGeoIPMatcherContainer(t *testing.T) {
@@ -217,10 +227,15 @@ func TestGeoIPMatcher6US(t *testing.T) {
} }
func loadGeoIP(country string) ([]*router.CIDR, error) { func loadGeoIP(country string) ([]*router.CIDR, error) {
geoipBytes, err := filesystem.ReadAsset("geoip.dat") path, err := getAssetPath("geoip.dat")
if err != nil { if err != nil {
return nil, err return nil, err
} }
geoipBytes, err := filesystem.ReadFile(path)
if err != nil {
return nil, err
}
var geoipList router.GeoIPList var geoipList router.GeoIPList
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil { if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
return nil, err return nil, err

View File

@@ -1,8 +1,6 @@
package router_test package router_test
import ( import (
"os"
"path/filepath"
"strconv" "strconv"
"testing" "testing"
@@ -10,7 +8,6 @@ import (
"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/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/protocol/http" "github.com/xtls/xray-core/common/protocol/http"
@@ -20,18 +17,6 @@ import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
func init() {
wd, err := os.Getwd()
common.Must(err)
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "release", "config", "geoip.dat")))
}
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "release", "config", "geosite.dat")))
}
}
func withBackground() routing.Context { func withBackground() routing.Context {
return &routing_session.Context{} return &routing_session.Context{}
} }
@@ -316,10 +301,15 @@ func TestRoutingRule(t *testing.T) {
} }
func loadGeoSite(country string) ([]*Domain, error) { func loadGeoSite(country string) ([]*Domain, error) {
geositeBytes, err := filesystem.ReadAsset("geosite.dat") path, err := getAssetPath("geosite.dat")
if err != nil { if err != nil {
return nil, err return nil, err
} }
geositeBytes, err := filesystem.ReadFile(path)
if err != nil {
return nil, err
}
var geositeList GeoSiteList var geositeList GeoSiteList
if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil { if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
return nil, err return nil, err

View File

@@ -58,8 +58,12 @@ type node struct {
RTTDeviationCost time.Duration RTTDeviationCost time.Duration
} }
func (l *LeastLoadStrategy) InjectContext(ctx context.Context) { func (s *LeastLoadStrategy) InjectContext(ctx context.Context) {
l.ctx = ctx s.ctx = ctx
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observer = observatory
return nil
}))
} }
func (s *LeastLoadStrategy) PickOutbound(candidates []string) string { func (s *LeastLoadStrategy) PickOutbound(candidates []string) string {
@@ -136,10 +140,8 @@ func (s *LeastLoadStrategy) selectLeastLoad(nodes []*node) []*node {
func (s *LeastLoadStrategy) getNodes(candidates []string, maxRTT time.Duration) []*node { func (s *LeastLoadStrategy) getNodes(candidates []string, maxRTT time.Duration) []*node {
if s.observer == nil { if s.observer == nil {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error { errors.LogError(s.ctx, "observer is nil")
s.observer = observatory return make([]*node, 0)
return nil
}))
} }
observeResult, err := s.observer.GetObservation(s.ctx) observeResult, err := s.observer.GetObservation(s.ctx)
if err != nil { if err != nil {

View File

@@ -7,64 +7,64 @@ import (
/* /*
Split into multiple package, need to be tested separately Split into multiple package, need to be tested separately
func TestSelectLeastLoad(t *testing.T) { func TestSelectLeastLoad(t *testing.T) {
settings := &StrategyLeastLoadConfig{ settings := &StrategyLeastLoadConfig{
HealthCheck: &HealthPingConfig{ HealthCheck: &HealthPingConfig{
SamplingCount: 10, SamplingCount: 10,
}, },
Expected: 1, Expected: 1,
MaxRTT: int64(time.Millisecond * time.Duration(800)), MaxRTT: int64(time.Millisecond * time.Duration(800)),
}
strategy := NewLeastLoadStrategy(settings)
// std 40
strategy.PutResult("a", time.Millisecond*time.Duration(60))
strategy.PutResult("a", time.Millisecond*time.Duration(140))
strategy.PutResult("a", time.Millisecond*time.Duration(60))
strategy.PutResult("a", time.Millisecond*time.Duration(140))
// std 60
strategy.PutResult("b", time.Millisecond*time.Duration(40))
strategy.PutResult("b", time.Millisecond*time.Duration(160))
strategy.PutResult("b", time.Millisecond*time.Duration(40))
strategy.PutResult("b", time.Millisecond*time.Duration(160))
// std 0, but >MaxRTT
strategy.PutResult("c", time.Millisecond*time.Duration(1000))
strategy.PutResult("c", time.Millisecond*time.Duration(1000))
strategy.PutResult("c", time.Millisecond*time.Duration(1000))
strategy.PutResult("c", time.Millisecond*time.Duration(1000))
expected := "a"
actual := strategy.SelectAndPick([]string{"a", "b", "c", "untested"})
if actual != expected {
t.Errorf("expected: %v, actual: %v", expected, actual)
}
} }
strategy := NewLeastLoadStrategy(settings)
// std 40
strategy.PutResult("a", time.Millisecond*time.Duration(60))
strategy.PutResult("a", time.Millisecond*time.Duration(140))
strategy.PutResult("a", time.Millisecond*time.Duration(60))
strategy.PutResult("a", time.Millisecond*time.Duration(140))
// std 60
strategy.PutResult("b", time.Millisecond*time.Duration(40))
strategy.PutResult("b", time.Millisecond*time.Duration(160))
strategy.PutResult("b", time.Millisecond*time.Duration(40))
strategy.PutResult("b", time.Millisecond*time.Duration(160))
// std 0, but >MaxRTT
strategy.PutResult("c", time.Millisecond*time.Duration(1000))
strategy.PutResult("c", time.Millisecond*time.Duration(1000))
strategy.PutResult("c", time.Millisecond*time.Duration(1000))
strategy.PutResult("c", time.Millisecond*time.Duration(1000))
expected := "a"
actual := strategy.SelectAndPick([]string{"a", "b", "c", "untested"})
if actual != expected {
t.Errorf("expected: %v, actual: %v", expected, actual)
}
}
func TestSelectLeastLoadWithCost(t *testing.T) { func TestSelectLeastLoadWithCost(t *testing.T) {
settings := &StrategyLeastLoadConfig{ settings := &StrategyLeastLoadConfig{
HealthCheck: &HealthPingConfig{ HealthCheck: &HealthPingConfig{
SamplingCount: 10, SamplingCount: 10,
}, },
Costs: []*StrategyWeight{ Costs: []*StrategyWeight{
{Match: "a", Value: 9}, {Match: "a", Value: 9},
}, },
Expected: 1, Expected: 1,
}
strategy := NewLeastLoadStrategy(settings, nil)
// std 40, std+c 120
strategy.PutResult("a", time.Millisecond*time.Duration(60))
strategy.PutResult("a", time.Millisecond*time.Duration(140))
strategy.PutResult("a", time.Millisecond*time.Duration(60))
strategy.PutResult("a", time.Millisecond*time.Duration(140))
// std 60
strategy.PutResult("b", time.Millisecond*time.Duration(40))
strategy.PutResult("b", time.Millisecond*time.Duration(160))
strategy.PutResult("b", time.Millisecond*time.Duration(40))
strategy.PutResult("b", time.Millisecond*time.Duration(160))
expected := "b"
actual := strategy.SelectAndPick([]string{"a", "b", "untested"})
if actual != expected {
t.Errorf("expected: %v, actual: %v", expected, actual)
}
} }
strategy := NewLeastLoadStrategy(settings, nil)
// std 40, std+c 120
strategy.PutResult("a", time.Millisecond*time.Duration(60))
strategy.PutResult("a", time.Millisecond*time.Duration(140))
strategy.PutResult("a", time.Millisecond*time.Duration(60))
strategy.PutResult("a", time.Millisecond*time.Duration(140))
// std 60
strategy.PutResult("b", time.Millisecond*time.Duration(40))
strategy.PutResult("b", time.Millisecond*time.Duration(160))
strategy.PutResult("b", time.Millisecond*time.Duration(40))
strategy.PutResult("b", time.Millisecond*time.Duration(160))
expected := "b"
actual := strategy.SelectAndPick([]string{"a", "b", "untested"})
if actual != expected {
t.Errorf("expected: %v, actual: %v", expected, actual)
}
}
*/ */
func TestSelectLeastExpected(t *testing.T) { func TestSelectLeastExpected(t *testing.T) {
strategy := &LeastLoadStrategy{ strategy := &LeastLoadStrategy{

View File

@@ -21,19 +21,20 @@ func (l *LeastPingStrategy) GetPrincipleTarget(strings []string) []string {
func (l *LeastPingStrategy) InjectContext(ctx context.Context) { func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
l.ctx = ctx l.ctx = ctx
common.Must(core.RequireFeatures(l.ctx, func(observatory extension.Observatory) error {
l.observatory = observatory
return nil
}))
} }
func (l *LeastPingStrategy) PickOutbound(strings []string) string { func (l *LeastPingStrategy) PickOutbound(strings []string) string {
if l.observatory == nil { if l.observatory == nil {
common.Must(core.RequireFeatures(l.ctx, func(observatory extension.Observatory) error { errors.LogError(l.ctx, "observer is nil")
l.observatory = observatory return ""
return nil
}))
} }
observeReport, err := l.observatory.GetObservation(l.ctx) observeReport, err := l.observatory.GetObservation(l.ctx)
if err != nil { if err != nil {
errors.LogInfoInner(l.ctx, err, "cannot get observe report") errors.LogInfoInner(l.ctx, err, "cannot get observer report")
return "" return ""
} }
outboundsList := outboundList(strings) outboundsList := outboundList(strings)

View File

@@ -11,7 +11,7 @@ import (
) )
// RandomStrategy represents a random balancing strategy // RandomStrategy represents a random balancing strategy
type RandomStrategy struct{ type RandomStrategy struct {
FallbackTag string FallbackTag string
ctx context.Context ctx context.Context
@@ -20,6 +20,12 @@ type RandomStrategy struct{
func (s *RandomStrategy) InjectContext(ctx context.Context) { func (s *RandomStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx s.ctx = ctx
if len(s.FallbackTag) > 0 {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
} }
func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string { func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string {
@@ -27,12 +33,6 @@ func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string {
} }
func (s *RandomStrategy) PickOutbound(candidates []string) string { func (s *RandomStrategy) PickOutbound(candidates []string) string {
if len(s.FallbackTag) > 0 && s.observatory == nil {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
if s.observatory != nil { if s.observatory != nil {
observeReport, err := s.observatory.GetObservation(s.ctx) observeReport, err := s.observatory.GetObservation(s.ctx)
if err == nil { if err == nil {

View File

@@ -1,8 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.35.1 // protoc-gen-go v1.35.1
// protoc v5.28.3 // protoc v5.28.2
// source: command.proto // source: app/stats/command/command.proto
package command package command
@@ -33,7 +33,7 @@ type GetStatsRequest struct {
func (x *GetStatsRequest) Reset() { func (x *GetStatsRequest) Reset() {
*x = GetStatsRequest{} *x = GetStatsRequest{}
mi := &file_command_proto_msgTypes[0] mi := &file_app_stats_command_command_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -45,7 +45,7 @@ func (x *GetStatsRequest) String() string {
func (*GetStatsRequest) ProtoMessage() {} func (*GetStatsRequest) ProtoMessage() {}
func (x *GetStatsRequest) ProtoReflect() protoreflect.Message { func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[0] mi := &file_app_stats_command_command_proto_msgTypes[0]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -58,7 +58,7 @@ func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetStatsRequest.ProtoReflect.Descriptor instead. // Deprecated: Use GetStatsRequest.ProtoReflect.Descriptor instead.
func (*GetStatsRequest) Descriptor() ([]byte, []int) { func (*GetStatsRequest) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{0} return file_app_stats_command_command_proto_rawDescGZIP(), []int{0}
} }
func (x *GetStatsRequest) GetName() string { func (x *GetStatsRequest) GetName() string {
@@ -86,7 +86,7 @@ type Stat struct {
func (x *Stat) Reset() { func (x *Stat) Reset() {
*x = Stat{} *x = Stat{}
mi := &file_command_proto_msgTypes[1] mi := &file_app_stats_command_command_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -98,7 +98,7 @@ func (x *Stat) String() string {
func (*Stat) ProtoMessage() {} func (*Stat) ProtoMessage() {}
func (x *Stat) ProtoReflect() protoreflect.Message { func (x *Stat) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[1] mi := &file_app_stats_command_command_proto_msgTypes[1]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -111,7 +111,7 @@ func (x *Stat) ProtoReflect() protoreflect.Message {
// Deprecated: Use Stat.ProtoReflect.Descriptor instead. // Deprecated: Use Stat.ProtoReflect.Descriptor instead.
func (*Stat) Descriptor() ([]byte, []int) { func (*Stat) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{1} return file_app_stats_command_command_proto_rawDescGZIP(), []int{1}
} }
func (x *Stat) GetName() string { func (x *Stat) GetName() string {
@@ -138,7 +138,7 @@ type GetStatsResponse struct {
func (x *GetStatsResponse) Reset() { func (x *GetStatsResponse) Reset() {
*x = GetStatsResponse{} *x = GetStatsResponse{}
mi := &file_command_proto_msgTypes[2] mi := &file_app_stats_command_command_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -150,7 +150,7 @@ func (x *GetStatsResponse) String() string {
func (*GetStatsResponse) ProtoMessage() {} func (*GetStatsResponse) ProtoMessage() {}
func (x *GetStatsResponse) ProtoReflect() protoreflect.Message { func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[2] mi := &file_app_stats_command_command_proto_msgTypes[2]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -163,7 +163,7 @@ func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetStatsResponse.ProtoReflect.Descriptor instead. // Deprecated: Use GetStatsResponse.ProtoReflect.Descriptor instead.
func (*GetStatsResponse) Descriptor() ([]byte, []int) { func (*GetStatsResponse) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{2} return file_app_stats_command_command_proto_rawDescGZIP(), []int{2}
} }
func (x *GetStatsResponse) GetStat() *Stat { func (x *GetStatsResponse) GetStat() *Stat {
@@ -184,7 +184,7 @@ type QueryStatsRequest struct {
func (x *QueryStatsRequest) Reset() { func (x *QueryStatsRequest) Reset() {
*x = QueryStatsRequest{} *x = QueryStatsRequest{}
mi := &file_command_proto_msgTypes[3] mi := &file_app_stats_command_command_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -196,7 +196,7 @@ func (x *QueryStatsRequest) String() string {
func (*QueryStatsRequest) ProtoMessage() {} func (*QueryStatsRequest) ProtoMessage() {}
func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message { func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[3] mi := &file_app_stats_command_command_proto_msgTypes[3]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -209,7 +209,7 @@ func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use QueryStatsRequest.ProtoReflect.Descriptor instead. // Deprecated: Use QueryStatsRequest.ProtoReflect.Descriptor instead.
func (*QueryStatsRequest) Descriptor() ([]byte, []int) { func (*QueryStatsRequest) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{3} return file_app_stats_command_command_proto_rawDescGZIP(), []int{3}
} }
func (x *QueryStatsRequest) GetPattern() string { func (x *QueryStatsRequest) GetPattern() string {
@@ -236,7 +236,7 @@ type QueryStatsResponse struct {
func (x *QueryStatsResponse) Reset() { func (x *QueryStatsResponse) Reset() {
*x = QueryStatsResponse{} *x = QueryStatsResponse{}
mi := &file_command_proto_msgTypes[4] mi := &file_app_stats_command_command_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -248,7 +248,7 @@ func (x *QueryStatsResponse) String() string {
func (*QueryStatsResponse) ProtoMessage() {} func (*QueryStatsResponse) ProtoMessage() {}
func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message { func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[4] mi := &file_app_stats_command_command_proto_msgTypes[4]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -261,7 +261,7 @@ func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use QueryStatsResponse.ProtoReflect.Descriptor instead. // Deprecated: Use QueryStatsResponse.ProtoReflect.Descriptor instead.
func (*QueryStatsResponse) Descriptor() ([]byte, []int) { func (*QueryStatsResponse) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{4} return file_app_stats_command_command_proto_rawDescGZIP(), []int{4}
} }
func (x *QueryStatsResponse) GetStat() []*Stat { func (x *QueryStatsResponse) GetStat() []*Stat {
@@ -279,7 +279,7 @@ type SysStatsRequest struct {
func (x *SysStatsRequest) Reset() { func (x *SysStatsRequest) Reset() {
*x = SysStatsRequest{} *x = SysStatsRequest{}
mi := &file_command_proto_msgTypes[5] mi := &file_app_stats_command_command_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -291,7 +291,7 @@ func (x *SysStatsRequest) String() string {
func (*SysStatsRequest) ProtoMessage() {} func (*SysStatsRequest) ProtoMessage() {}
func (x *SysStatsRequest) ProtoReflect() protoreflect.Message { func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[5] mi := &file_app_stats_command_command_proto_msgTypes[5]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -304,7 +304,7 @@ func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use SysStatsRequest.ProtoReflect.Descriptor instead. // Deprecated: Use SysStatsRequest.ProtoReflect.Descriptor instead.
func (*SysStatsRequest) Descriptor() ([]byte, []int) { func (*SysStatsRequest) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{5} return file_app_stats_command_command_proto_rawDescGZIP(), []int{5}
} }
type SysStatsResponse struct { type SysStatsResponse struct {
@@ -326,7 +326,7 @@ type SysStatsResponse struct {
func (x *SysStatsResponse) Reset() { func (x *SysStatsResponse) Reset() {
*x = SysStatsResponse{} *x = SysStatsResponse{}
mi := &file_command_proto_msgTypes[6] mi := &file_app_stats_command_command_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -338,7 +338,7 @@ func (x *SysStatsResponse) String() string {
func (*SysStatsResponse) ProtoMessage() {} func (*SysStatsResponse) ProtoMessage() {}
func (x *SysStatsResponse) ProtoReflect() protoreflect.Message { func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[6] mi := &file_app_stats_command_command_proto_msgTypes[6]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -351,7 +351,7 @@ func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use SysStatsResponse.ProtoReflect.Descriptor instead. // Deprecated: Use SysStatsResponse.ProtoReflect.Descriptor instead.
func (*SysStatsResponse) Descriptor() ([]byte, []int) { func (*SysStatsResponse) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{6} return file_app_stats_command_command_proto_rawDescGZIP(), []int{6}
} }
func (x *SysStatsResponse) GetNumGoroutine() uint32 { func (x *SysStatsResponse) GetNumGoroutine() uint32 {
@@ -432,7 +432,7 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
mi := &file_command_proto_msgTypes[7] mi := &file_app_stats_command_command_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -444,7 +444,7 @@ func (x *Config) String() string {
func (*Config) ProtoMessage() {} func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[7] mi := &file_app_stats_command_command_proto_msgTypes[7]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -457,104 +457,105 @@ func (x *Config) ProtoReflect() protoreflect.Message {
// Deprecated: Use Config.ProtoReflect.Descriptor instead. // Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) { func (*Config) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{7} return file_app_stats_command_command_proto_rawDescGZIP(), []int{7}
} }
var File_command_proto protoreflect.FileDescriptor var File_app_stats_command_command_proto protoreflect.FileDescriptor
var file_command_proto_rawDesc = []byte{ var file_app_stats_command_command_proto_rawDesc = []byte{
0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x1f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
0x16, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x3b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x12, 0x16, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74,
0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x3b, 0x0a, 0x0f, 0x47, 0x65, 0x74,
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
0x0a, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72,
0x65, 0x73, 0x65, 0x74, 0x22, 0x30, 0x0a, 0x04, 0x53, 0x74, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x44, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x22, 0x30, 0x0a, 0x04, 0x53, 0x74, 0x61, 0x74, 0x12, 0x12,
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x73, 0x74, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x44, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53,
0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x04, 0x73, 0x74, 0x61, 0x74, 0x22, 0x43, 0x0a, 0x11, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04,
0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x73, 0x74, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61,
0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x72,
0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x73, 0x65,
0x74, 0x22, 0x46, 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x73, 0x74, 0x61, 0x74, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53,
0x74, 0x61, 0x74, 0x52, 0x04, 0x73, 0x74, 0x61, 0x74, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x79, 0x73,
0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa2, 0x02, 0x0a,
0x10, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x22, 0x0a, 0x0c, 0x4e, 0x75, 0x6d, 0x47, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x4e, 0x75, 0x6d, 0x47, 0x6f, 0x72, 0x6f,
0x75, 0x74, 0x69, 0x6e, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x75, 0x6d, 0x47, 0x43, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x4e, 0x75, 0x6d, 0x47, 0x43, 0x12, 0x14, 0x0a, 0x05, 0x41,
0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x41, 0x6c, 0x6c, 0x6f,
0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x18,
0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f,
0x63, 0x12, 0x10, 0x0a, 0x03, 0x53, 0x79, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03,
0x53, 0x79, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x06,
0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x4d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x12, 0x14, 0x0a,
0x05, 0x46, 0x72, 0x65, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x46, 0x72,
0x65, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4c, 0x69, 0x76, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4c, 0x69, 0x76, 0x65, 0x4f, 0x62,
0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x61, 0x75, 0x73, 0x65, 0x54, 0x6f,
0x74, 0x61, 0x6c, 0x4e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x50, 0x61, 0x75,
0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x70, 0x74,
0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x70, 0x74, 0x69, 0x6d,
0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xa1, 0x03, 0x0a, 0x0c,
0x53, 0x74, 0x61, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x08,
0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61,
0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74,
0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a,
0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12,
0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61,
0x74, 0x73, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74,
0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72,
0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, 0x0a, 0x0b, 0x47,
0x65, 0x74, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x04, 0x73, 0x74, 0x61, 0x74, 0x22, 0x43,
0x0a, 0x11, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x14, 0x0a,
0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65,
0x73, 0x65, 0x74, 0x22, 0x46, 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x73, 0x74, 0x61,
0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x04, 0x73, 0x74, 0x61, 0x74, 0x22, 0x11, 0x0a, 0x0f, 0x53,
0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa2,
0x02, 0x0a, 0x10, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x4e, 0x75, 0x6d, 0x47, 0x6f, 0x72, 0x6f, 0x75, 0x74,
0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x4e, 0x75, 0x6d, 0x47, 0x6f,
0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x75, 0x6d, 0x47, 0x43,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x4e, 0x75, 0x6d, 0x47, 0x43, 0x12, 0x14, 0x0a,
0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x41, 0x6c,
0x6c, 0x6f, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f,
0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c,
0x6c, 0x6f, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x53, 0x79, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04,
0x52, 0x03, 0x53, 0x79, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73,
0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x4d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x12,
0x14, 0x0a, 0x05, 0x46, 0x72, 0x65, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05,
0x46, 0x72, 0x65, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4c, 0x69, 0x76, 0x65, 0x4f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4c, 0x69, 0x76, 0x65,
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x61, 0x75, 0x73, 0x65,
0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x50,
0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x55,
0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x70, 0x74,
0x69, 0x6d, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xa1, 0x03,
0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f,
0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73,
0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74,
0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e,
0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x65, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61,
0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74,
0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61,
0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x16, 0x58, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
0x74, 0x61, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75,
0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, 0x0a,
0x0b, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53,
0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x42, 0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50,
0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70,
0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02,
0x16, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e,
0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
file_command_proto_rawDescOnce sync.Once file_app_stats_command_command_proto_rawDescOnce sync.Once
file_command_proto_rawDescData = file_command_proto_rawDesc file_app_stats_command_command_proto_rawDescData = file_app_stats_command_command_proto_rawDesc
) )
func file_command_proto_rawDescGZIP() []byte { func file_app_stats_command_command_proto_rawDescGZIP() []byte {
file_command_proto_rawDescOnce.Do(func() { file_app_stats_command_command_proto_rawDescOnce.Do(func() {
file_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_command_proto_rawDescData) file_app_stats_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_stats_command_command_proto_rawDescData)
}) })
return file_command_proto_rawDescData return file_app_stats_command_command_proto_rawDescData
} }
var file_command_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_app_stats_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_command_proto_goTypes = []any{ var file_app_stats_command_command_proto_goTypes = []any{
(*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest (*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest
(*Stat)(nil), // 1: xray.app.stats.command.Stat (*Stat)(nil), // 1: xray.app.stats.command.Stat
(*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse (*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse
@@ -564,7 +565,7 @@ var file_command_proto_goTypes = []any{
(*SysStatsResponse)(nil), // 6: xray.app.stats.command.SysStatsResponse (*SysStatsResponse)(nil), // 6: xray.app.stats.command.SysStatsResponse
(*Config)(nil), // 7: xray.app.stats.command.Config (*Config)(nil), // 7: xray.app.stats.command.Config
} }
var file_command_proto_depIdxs = []int32{ var file_app_stats_command_command_proto_depIdxs = []int32{
1, // 0: xray.app.stats.command.GetStatsResponse.stat:type_name -> xray.app.stats.command.Stat 1, // 0: xray.app.stats.command.GetStatsResponse.stat:type_name -> xray.app.stats.command.Stat
1, // 1: xray.app.stats.command.QueryStatsResponse.stat:type_name -> xray.app.stats.command.Stat 1, // 1: xray.app.stats.command.QueryStatsResponse.stat:type_name -> xray.app.stats.command.Stat
0, // 2: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest 0, // 2: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest
@@ -582,27 +583,27 @@ var file_command_proto_depIdxs = []int32{
0, // [0:2] is the sub-list for field type_name 0, // [0:2] is the sub-list for field type_name
} }
func init() { file_command_proto_init() } func init() { file_app_stats_command_command_proto_init() }
func file_command_proto_init() { func file_app_stats_command_command_proto_init() {
if File_command_proto != nil { if File_app_stats_command_command_proto != nil {
return return
} }
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_command_proto_rawDesc, RawDescriptor: file_app_stats_command_command_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 8, NumMessages: 8,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },
GoTypes: file_command_proto_goTypes, GoTypes: file_app_stats_command_command_proto_goTypes,
DependencyIndexes: file_command_proto_depIdxs, DependencyIndexes: file_app_stats_command_command_proto_depIdxs,
MessageInfos: file_command_proto_msgTypes, MessageInfos: file_app_stats_command_command_proto_msgTypes,
}.Build() }.Build()
File_command_proto = out.File File_app_stats_command_command_proto = out.File
file_command_proto_rawDesc = nil file_app_stats_command_command_proto_rawDesc = nil
file_command_proto_goTypes = nil file_app_stats_command_command_proto_goTypes = nil
file_command_proto_depIdxs = nil file_app_stats_command_command_proto_depIdxs = nil
} }

View File

@@ -1,8 +1,8 @@
// 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.5.1 // - protoc-gen-go-grpc v1.5.1
// - protoc v5.28.3 // - protoc v5.28.2
// source: command.proto // source: app/stats/command/command.proto
package command package command
@@ -231,5 +231,5 @@ var StatsService_ServiceDesc = grpc.ServiceDesc{
}, },
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "command.proto", Metadata: "app/stats/command/command.proto",
} }

View File

@@ -218,7 +218,7 @@ func (b *Buffer) Cap() int32 {
// NewWithSize creates a Buffer with 0 length and capacity with at least the given size. // NewWithSize creates a Buffer with 0 length and capacity with at least the given size.
func NewWithSize(size int32) *Buffer { func NewWithSize(size int32) *Buffer {
return &Buffer{ return &Buffer{
v: bytespool.Alloc(size), v: bytespool.Alloc(size),
} }
} }

View File

@@ -38,7 +38,7 @@ func Error2(v interface{}, err error) error {
func envFile() (string, error) { func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" { if file := os.Getenv("GOENV"); file != "" {
if file == "off" { if file == "off" {
return "", fmt.Errorf("GOENV=off") return "", errors.New("GOENV=off")
} }
return file, nil return file, nil
} }
@@ -47,7 +47,7 @@ func envFile() (string, error) {
return "", err return "", err
} }
if dir == "" { if dir == "" {
return "", fmt.Errorf("missing user-config dir") return "", errors.New("missing user-config dir")
} }
return filepath.Join(dir, "go", "env"), nil return filepath.Join(dir, "go", "env"), nil
} }
@@ -60,7 +60,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err return "", err
} }
if file == "" { if file == "" {
return "", fmt.Errorf("missing runtime env file") return "", errors.New("missing runtime env file")
} }
var data []byte var data []byte
var runtimeEnv string var runtimeEnv string

View File

@@ -7,7 +7,7 @@ type SessionKey int
// ID of a session. // ID of a session.
type ID uint32 type ID uint32
const( const (
idSessionKey SessionKey = 0 idSessionKey SessionKey = 0
) )

View File

@@ -16,6 +16,7 @@ func TestFileLogger(t *testing.T) {
common.Must(err) common.Must(err)
path := f.Name() path := f.Name()
common.Must(f.Close()) common.Must(f.Close())
defer os.Remove(path)
creator, err := CreateFileLogWriter(path) creator, err := CreateFileLogWriter(path)
common.Must(err) common.Must(err)

View File

@@ -1,13 +1,14 @@
package quic package quic
import ( import (
"context"
"crypto" "crypto"
"crypto/aes" "crypto/aes"
"crypto/tls" "crypto/tls"
"encoding/binary" "encoding/binary"
"io" "io"
"github.com/quic-go/quic-go/quicvarint" "github.com/xtls/quic-go/quicvarint"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/bytespool" "github.com/xtls/xray-core/common/bytespool"
@@ -46,7 +47,18 @@ var (
errNotQuicInitial = errors.New("not initial packet") errNotQuicInitial = errors.New("not initial packet")
) )
func SniffQUIC(b []byte) (*SniffHeader, error) { func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
// In extremely rare cases, this sniffer may cause slice error
// and we set recover() here to prevent crash.
// TODO: Thoroughly fix this panic
defer func() {
if r := recover(); r != nil {
errors.LogError(context.Background(), "Failed to sniff QUIC: ", r)
resultReturn = nil
errorReturn = common.ErrNoClue
}
}()
// Crypto data separated across packets // Crypto data separated across packets
cryptoLen := 0 cryptoLen := 0
cryptoData := bytespool.Alloc(int32(len(b))) cryptoData := bytespool.Alloc(int32(len(b)))

View File

@@ -7,7 +7,7 @@ import (
func (u *User) GetTypedAccount() (Account, error) { func (u *User) GetTypedAccount() (Account, error) {
if u.GetAccount() == nil { if u.GetAccount() == nil {
return nil, errors.New("Account missing").AtWarning() return nil, errors.New("Account is missing").AtWarning()
} }
rawAccount, err := u.Account.GetInstance() rawAccount, err := u.Account.GetInstance()
@@ -41,8 +41,8 @@ func ToProtoUser(mu *MemoryUser) *User {
} }
return &User{ return &User{
Account: serial.ToTypedMessage(mu.Account.ToProto()), Account: serial.ToTypedMessage(mu.Account.ToProto()),
Email: mu.Email, Email: mu.Email,
Level: mu.Level, Level: mu.Level,
} }
} }

View File

@@ -22,12 +22,12 @@ func MarshalToJson(v interface{}, insertTypeInfo bool) (string, bool) {
} }
func JSONMarshalWithoutEscape(t interface{}) ([]byte, error) { func JSONMarshalWithoutEscape(t interface{}) ([]byte, error) {
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
encoder := json.NewEncoder(buffer) encoder := json.NewEncoder(buffer)
encoder.SetIndent("", " ") encoder.SetIndent("", " ")
encoder.SetEscapeHTML(false) encoder.SetEscapeHTML(false)
err := encoder.Encode(t) err := encoder.Encode(t)
return buffer.Bytes(), err return buffer.Bytes(), err
} }
func marshalTypedMessage(v *cserial.TypedMessage, ignoreNullValue bool, insertTypeInfo bool) interface{} { func marshalTypedMessage(v *cserial.TypedMessage, ignoreNullValue bool, insertTypeInfo bool) interface{} {

View File

@@ -204,9 +204,7 @@ func getConfig() string {
"security": "none", "security": "none",
"wsSettings": { "wsSettings": {
"path": "/?ed=2048", "path": "/?ed=2048",
"headers": { "host": "bing.com"
"Host": "bing.com"
}
} }
} }
} }

View File

@@ -148,4 +148,4 @@ func (c *Content) AttributeLen() int {
c.mu.Unlock() c.mu.Unlock()
}() }()
return len(c.Attributes) return len(c.Attributes)
} }

View File

@@ -48,9 +48,9 @@ func (d *XrayOutboundDialer) DialContext(ctx context.Context, network string, de
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.Target = ToDestination(destination, ToNetwork(network)) ob.Target = ToDestination(destination, ToNetwork(network))
opts := []pipe.Option{pipe.WithSizeLimit(64 * 1024)} opts := []pipe.Option{pipe.WithSizeLimit(64 * 1024)}
uplinkReader, uplinkWriter := pipe.New(opts...) uplinkReader, uplinkWriter := pipe.New(opts...)
downlinkReader, downlinkWriter := pipe.New(opts...) downlinkReader, downlinkWriter := pipe.New(opts...)

View File

@@ -30,7 +30,7 @@ type ConfigLoader func(input interface{}) (*Config, error)
// ConfigBuilder is a builder to build core.Config from filenames and formats // ConfigBuilder is a builder to build core.Config from filenames and formats
type ConfigBuilder func(files []*ConfigSource) (*Config, error) type ConfigBuilder func(files []*ConfigSource) (*Config, error)
// ConfigsMerger merge multiple json configs into on config // ConfigsMerger merges multiple json configs into a single one
type ConfigsMerger func(files []*ConfigSource) (string, error) type ConfigsMerger func(files []*ConfigSource) (string, error)
var ( var (

View File

@@ -18,8 +18,8 @@ import (
var ( var (
Version_x byte = 24 Version_x byte = 24
Version_y byte = 11 Version_y byte = 12
Version_z byte = 5 Version_z byte = 31
) )
var ( var (

View File

@@ -44,22 +44,13 @@ func getFeature(allFeatures []features.Feature, t reflect.Type) features.Feature
return nil return nil
} }
func (r *resolution) resolve(allFeatures []features.Feature) (bool, error) { func (r *resolution) callbackResolution(allFeatures []features.Feature) error {
var fs []features.Feature
for _, d := range r.deps {
f := getFeature(allFeatures, d)
if f == nil {
return false, nil
}
fs = append(fs, f)
}
callback := reflect.ValueOf(r.callback) callback := reflect.ValueOf(r.callback)
var input []reflect.Value var input []reflect.Value
callbackType := callback.Type() callbackType := callback.Type()
for i := 0; i < callbackType.NumIn(); i++ { for i := 0; i < callbackType.NumIn(); i++ {
pt := callbackType.In(i) pt := callbackType.In(i)
for _, f := range fs { for _, f := range allFeatures {
if reflect.TypeOf(f).AssignableTo(pt) { if reflect.TypeOf(f).AssignableTo(pt) {
input = append(input, reflect.ValueOf(f)) input = append(input, reflect.ValueOf(f))
break break
@@ -84,15 +75,17 @@ func (r *resolution) resolve(allFeatures []features.Feature) (bool, error) {
} }
} }
return true, err return err
} }
// Instance combines all functionalities in Xray. // Instance combines all Xray features.
type Instance struct { type Instance struct {
access sync.Mutex statusLock sync.Mutex
features []features.Feature features []features.Feature
featureResolutions []resolution pendingResolutions []resolution
running bool pendingOptionalResolutions []resolution
running bool
resolveLock sync.Mutex
ctx context.Context ctx context.Context
} }
@@ -153,7 +146,14 @@ func addOutboundHandlers(server *Instance, configs []*OutboundHandlerConfig) err
// See Instance.RequireFeatures for more information. // See Instance.RequireFeatures for more information.
func RequireFeatures(ctx context.Context, callback interface{}) error { func RequireFeatures(ctx context.Context, callback interface{}) error {
v := MustFromContext(ctx) v := MustFromContext(ctx)
return v.RequireFeatures(callback) return v.RequireFeatures(callback, false)
}
// OptionalFeatures is a helper function to aquire features from Instance in context.
// See Instance.RequireFeatures for more information.
func OptionalFeatures(ctx context.Context, callback interface{}) error {
v := MustFromContext(ctx)
return v.RequireFeatures(callback, true)
} }
// New returns a new Xray instance based on given configuration. // New returns a new Xray instance based on given configuration.
@@ -227,9 +227,12 @@ func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
}(), }(),
) )
if server.featureResolutions != nil { server.resolveLock.Lock()
return true, errors.New("not all dependency are resolved.") if server.pendingResolutions != nil {
server.resolveLock.Unlock()
return true, errors.New("not all dependencies are resolved.")
} }
server.resolveLock.Unlock()
if err := addInboundHandlers(server, config.Inbound); err != nil { if err := addInboundHandlers(server, config.Inbound); err != nil {
return true, err return true, err
@@ -248,8 +251,8 @@ func (s *Instance) Type() interface{} {
// Close shutdown the Xray instance. // Close shutdown the Xray instance.
func (s *Instance) Close() error { func (s *Instance) Close() error {
s.access.Lock() s.statusLock.Lock()
defer s.access.Unlock() defer s.statusLock.Unlock()
s.running = false s.running = false
@@ -268,7 +271,7 @@ func (s *Instance) Close() error {
// RequireFeatures registers a callback, which will be called when all dependent features are registered. // RequireFeatures registers a callback, which will be called when all dependent features are registered.
// The callback must be a func(). All its parameters must be features.Feature. // The callback must be a func(). All its parameters must be features.Feature.
func (s *Instance) RequireFeatures(callback interface{}) error { func (s *Instance) RequireFeatures(callback interface{}, optional bool) error {
callbackType := reflect.TypeOf(callback) callbackType := reflect.TypeOf(callback)
if callbackType.Kind() != reflect.Func { if callbackType.Kind() != reflect.Func {
panic("not a function") panic("not a function")
@@ -283,17 +286,32 @@ func (s *Instance) RequireFeatures(callback interface{}) error {
deps: featureTypes, deps: featureTypes,
callback: callback, callback: callback,
} }
if finished, err := r.resolve(s.features); finished {
return err s.resolveLock.Lock()
foundAll := true
for _, d := range r.deps {
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
}
if foundAll {
s.resolveLock.Unlock()
return r.callbackResolution(s.features)
} else {
if optional {
s.pendingOptionalResolutions = append(s.pendingOptionalResolutions, r)
} else {
s.pendingResolutions = append(s.pendingResolutions, r)
}
s.resolveLock.Unlock()
return nil
} }
s.featureResolutions = append(s.featureResolutions, r)
return nil
} }
// AddFeature registers a feature into current Instance. // AddFeature registers a feature into current Instance.
func (s *Instance) AddFeature(feature features.Feature) error { func (s *Instance) AddFeature(feature features.Feature) error {
s.features = append(s.features, feature)
if s.running { if s.running {
if err := feature.Start(); err != nil { if err := feature.Start(); err != nil {
errors.LogInfoInner(s.ctx, err, "failed to start feature") errors.LogInfoInner(s.ctx, err, "failed to start feature")
@@ -301,27 +319,52 @@ func (s *Instance) AddFeature(feature features.Feature) error {
return nil return nil
} }
if s.featureResolutions == nil { s.resolveLock.Lock()
return nil s.features = append(s.features, feature)
}
var pendingResolutions []resolution var availableResolution []resolution
for _, r := range s.featureResolutions { var pending []resolution
finished, err := r.resolve(s.features) for _, r := range s.pendingResolutions {
if finished && err != nil { foundAll := true
return err for _, d := range r.deps {
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
} }
if !finished { if foundAll {
pendingResolutions = append(pendingResolutions, r) availableResolution = append(availableResolution, r)
} else {
pending = append(pending, r)
} }
} }
if len(pendingResolutions) == 0 { s.pendingResolutions = pending
s.featureResolutions = nil
} else if len(pendingResolutions) < len(s.featureResolutions) {
s.featureResolutions = pendingResolutions
}
return nil var pendingOptional []resolution
for _, r := range s.pendingOptionalResolutions {
foundAll := true
for _, d := range r.deps {
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
}
if foundAll {
availableResolution = append(availableResolution, r)
} else {
pendingOptional = append(pendingOptional, r)
}
}
s.pendingOptionalResolutions = pendingOptional
s.resolveLock.Unlock()
var err error
for _, r := range availableResolution {
err = r.callbackResolution(s.features) // only return the last error for now
}
return err
} }
// GetFeature returns a feature of the given type, or nil if such feature is not registered. // GetFeature returns a feature of the given type, or nil if such feature is not registered.
@@ -334,8 +377,8 @@ func (s *Instance) GetFeature(featureType interface{}) features.Feature {
// //
// xray:api:stable // xray:api:stable
func (s *Instance) Start() error { func (s *Instance) Start() error {
s.access.Lock() s.statusLock.Lock()
defer s.access.Unlock() defer s.statusLock.Unlock()
s.running = true s.running = true
for _, f := range s.features { for _, f := range s.features {

View File

@@ -30,7 +30,7 @@ func TestXrayDependency(t *testing.T) {
t.Error("expected dns client fulfilled, but actually nil") t.Error("expected dns client fulfilled, but actually nil")
} }
wait <- true wait <- true
}) }, false)
instance.AddFeature(localdns.New()) instance.AddFeature(localdns.New())
<-wait <-wait
} }
@@ -54,8 +54,8 @@ func TestXrayClose(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(net.LocalHostIP), Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(0), Port: uint32(0),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },

View File

@@ -125,7 +125,7 @@ func (ctx *Context) GetSkipDNSResolve() bool {
// AsRoutingContext creates a context from context.context with session info. // AsRoutingContext creates a context from context.context with session info.
func AsRoutingContext(ctx context.Context) routing.Context { func AsRoutingContext(ctx context.Context) routing.Context {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
return &Context{ return &Context{
Inbound: session.InboundFromContext(ctx), Inbound: session.InboundFromContext(ctx),
Outbound: ob, Outbound: ob,

18
go.mod
View File

@@ -12,23 +12,23 @@ require (
github.com/miekg/dns v1.1.62 github.com/miekg/dns v1.1.62
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/pires/go-proxyproto v0.8.0 github.com/pires/go-proxyproto v0.8.0
github.com/quic-go/quic-go v0.46.0
github.com/refraction-networking/utls v1.6.7 github.com/refraction-networking/utls v1.6.7
github.com/sagernet/sing v0.4.3 github.com/sagernet/sing v0.5.1
github.com/sagernet/sing-shadowsocks v0.2.7 github.com/sagernet/sing-shadowsocks v0.2.7
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.10.0
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
github.com/vishvananda/netlink v1.3.0 github.com/vishvananda/netlink v1.3.0
github.com/xtls/quic-go v0.0.0-20241220091641-6f5777d1c087
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.28.0 golang.org/x/crypto v0.31.0
golang.org/x/net v0.30.0 golang.org/x/net v0.33.0
golang.org/x/sync v0.8.0 golang.org/x/sync v0.10.0
golang.org/x/sys v0.26.0 golang.org/x/sys v0.28.0
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
google.golang.org/grpc v1.67.1 google.golang.org/grpc v1.67.1
google.golang.org/protobuf v1.35.1 google.golang.org/protobuf v1.36.1
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489
h12.io/socks v1.0.3 h12.io/socks v1.0.3
lukechampine.com/blake3 v1.3.0 lukechampine.com/blake3 v1.3.0
@@ -51,7 +51,7 @@ require (
go.uber.org/mock v0.4.0 // indirect go.uber.org/mock v0.4.0 // indirect
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
golang.org/x/mod v0.18.0 // indirect golang.org/x/mod v0.18.0 // indirect
golang.org/x/text v0.19.0 // indirect golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.5.0 // indirect golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.22.0 // indirect golang.org/x/tools v0.22.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect

36
go.sum
View File

@@ -48,28 +48,28 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y=
github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8= github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y=
github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= github.com/sagernet/sing v0.5.1/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4= github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xtls/quic-go v0.0.0-20241220091641-6f5777d1c087 h1:kKPg/cJPSKnE50VXVBskDYYSBkl4X3sMCIbTy+XKNGk=
github.com/xtls/quic-go v0.0.0-20241220091641-6f5777d1c087/go.mod h1:mN9lAuc8Vt7eHvnQkDIH5+uHh+DcLmTBma9rLqk/rPY=
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg= github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg=
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE= github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
@@ -79,8 +79,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
@@ -89,12 +89,12 @@ golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -103,14 +103,14 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -129,8 +129,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -42,6 +42,10 @@ type Address struct {
net.Address net.Address
} }
func (v Address) MarshalJSON() ([]byte, error) {
return json.Marshal(v.Address.String())
}
func (v *Address) UnmarshalJSON(data []byte) error { func (v *Address) UnmarshalJSON(data []byte) error {
var rawStr string var rawStr string
if err := json.Unmarshal(data, &rawStr); err != nil { if err := json.Unmarshal(data, &rawStr); err != nil {

View File

@@ -13,7 +13,7 @@ type DNSOutboundConfig struct {
Port uint16 `json:"port"` Port uint16 `json:"port"`
UserLevel uint32 `json:"userLevel"` UserLevel uint32 `json:"userLevel"`
NonIPQuery string `json:"nonIPQuery"` NonIPQuery string `json:"nonIPQuery"`
BlockTypes []int32 `json:"blockTypes"` BlockTypes []int32 `json:"blockTypes"`
} }
func (c *DNSOutboundConfig) Build() (proto.Message, error) { func (c *DNSOutboundConfig) Build() (proto.Message, error) {

View File

@@ -2,57 +2,15 @@ package conf_test
import ( import (
"encoding/json" "encoding/json"
"os"
"path/filepath"
"testing" "testing"
"github.com/xtls/xray-core/app/dns" "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem"
. "github.com/xtls/xray-core/infra/conf" . "github.com/xtls/xray-core/infra/conf"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
func init() {
wd, err := os.Getwd()
common.Must(err)
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
}
geositeFilePath := filepath.Join(wd, "geosite.dat")
os.Setenv("xray.location.asset", wd)
geositeFile, err := os.OpenFile(geositeFilePath, os.O_CREATE|os.O_WRONLY, 0o600)
common.Must(err)
defer geositeFile.Close()
list := &router.GeoSiteList{
Entry: []*router.GeoSite{
{
CountryCode: "TEST",
Domain: []*router.Domain{
{Type: router.Domain_Full, Value: "example.com"},
},
},
},
}
listBytes, err := proto.Marshal(list)
common.Must(err)
common.Must2(geositeFile.Write(listBytes))
}
func TestDNSConfigParsing(t *testing.T) { func TestDNSConfigParsing(t *testing.T) {
geositePath := platform.GetAssetLocation("geosite.dat")
defer func() {
os.Remove(geositePath)
os.Unsetenv("xray.location.asset")
}()
parserCreator := func() func(string) (proto.Message, error) { parserCreator := func() func(string) (proto.Message, error) {
return func(s string) (proto.Message, error) { return func(s string) (proto.Message, error) {
config := new(DNSConfig) config := new(DNSConfig)

View File

@@ -6,11 +6,11 @@ import (
) )
type DokodemoConfig struct { type DokodemoConfig struct {
Host *Address `json:"address"` Host *Address `json:"address"`
PortValue uint16 `json:"port"` PortValue uint16 `json:"port"`
NetworkList *NetworkList `json:"network"` NetworkList *NetworkList `json:"network"`
Redirect bool `json:"followRedirect"` Redirect bool `json:"followRedirect"`
UserLevel uint32 `json:"userLevel"` UserLevel uint32 `json:"userLevel"`
} }
func (v *DokodemoConfig) Build() (proto.Message, error) { func (v *DokodemoConfig) Build() (proto.Message, error) {

View File

@@ -2,7 +2,7 @@ package conf
import ( import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/app/observatory/burst" "github.com/xtls/xray-core/app/observatory/burst"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration" "github.com/xtls/xray-core/infra/conf/cfgcommon/duration"

View File

@@ -71,9 +71,9 @@ func (r *BalancingRule) Build() (*router.BalancingRule, error) {
} }
type RouterConfig struct { type RouterConfig struct {
RuleList []json.RawMessage `json:"rules"` RuleList []json.RawMessage `json:"rules"`
DomainStrategy *string `json:"domainStrategy"` DomainStrategy *string `json:"domainStrategy"`
Balancers []*BalancingRule `json:"balancers"` Balancers []*BalancingRule `json:"balancers"`
DomainMatcher string `json:"domainMatcher"` DomainMatcher string `json:"domainMatcher"`
} }

View File

@@ -2,9 +2,9 @@ package conf
import ( import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/app/observatory/burst" "github.com/xtls/xray-core/app/observatory/burst"
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration" "github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
) )
@@ -46,10 +46,10 @@ type strategyLeastLoadConfig struct {
// healthCheckSettings holds settings for health Checker // healthCheckSettings holds settings for health Checker
type healthCheckSettings struct { type healthCheckSettings struct {
Destination string `json:"destination"` Destination string `json:"destination"`
Connectivity string `json:"connectivity"` Connectivity string `json:"connectivity"`
Interval duration.Duration `json:"interval"` Interval duration.Duration `json:"interval"`
SamplingCount int `json:"sampling"` SamplingCount int `json:"sampling"`
Timeout duration.Duration `json:"timeout"` Timeout duration.Duration `json:"timeout"`
} }

View File

@@ -2,6 +2,7 @@ package conf_test
import ( import (
"encoding/json" "encoding/json"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@@ -18,21 +19,44 @@ import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
func init() { func getAssetPath(file string) (string, error) {
wd, err := os.Getwd() path := platform.GetAssetLocation(file)
common.Must(err) _, err := os.Stat(path)
if os.IsNotExist(err) {
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) { path := filepath.Join("..", "..", "resources", file)
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat"))) _, err := os.Stat(path)
if os.IsNotExist(err) {
return "", fmt.Errorf("can't find %s in standard asset locations or {project_root}/resources", file)
}
if err != nil {
return "", fmt.Errorf("can't stat %s: %v", path, err)
}
return path, nil
}
if err != nil {
return "", fmt.Errorf("can't stat %s: %v", path, err)
} }
os.Setenv("xray.location.asset", wd) return path, nil
} }
func TestToCidrList(t *testing.T) { func TestToCidrList(t *testing.T) {
t.Log(os.Getenv("xray.location.asset")) tempDir, err := os.MkdirTemp("", "test-")
if err != nil {
t.Fatalf("can't create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoiptestrouter.dat"), "geoip.dat")) geoipPath, err := getAssetPath("geoip.dat")
if err != nil {
t.Fatal(err)
}
common.Must(filesystem.CopyFile(filepath.Join(tempDir, "geoip.dat"), geoipPath))
common.Must(filesystem.CopyFile(filepath.Join(tempDir, "geoiptestrouter.dat"), geoipPath))
os.Setenv("xray.location.asset", tempDir)
defer os.Unsetenv("xray.location.asset")
ips := StringList([]string{ ips := StringList([]string{
"geoip:us", "geoip:us",
@@ -44,7 +68,7 @@ func TestToCidrList(t *testing.T) {
"ext-ip:geoiptestrouter.dat:!ca", "ext-ip:geoiptestrouter.dat:!ca",
}) })
_, err := ToCidrList(ips) _, err = ToCidrList(ips)
if err != nil { if err != nil {
t.Fatalf("Failed to parse geoip list, got %s", err) t.Fatalf("Failed to parse geoip list, got %s", err)
} }

View File

@@ -16,8 +16,6 @@ import (
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
httpheader "github.com/xtls/xray-core/transport/internet/headers/http"
"github.com/xtls/xray-core/transport/internet/http"
"github.com/xtls/xray-core/transport/internet/httpupgrade" "github.com/xtls/xray-core/transport/internet/httpupgrade"
"github.com/xtls/xray-core/transport/internet/kcp" "github.com/xtls/xray-core/transport/internet/kcp"
"github.com/xtls/xray-core/transport/internet/reality" "github.com/xtls/xray-core/transport/internet/reality"
@@ -149,6 +147,7 @@ type WebSocketConfig struct {
Path string `json:"path"` Path string `json:"path"`
Headers map[string]string `json:"headers"` Headers map[string]string `json:"headers"`
AcceptProxyProtocol bool `json:"acceptProxyProtocol"` AcceptProxyProtocol bool `json:"acceptProxyProtocol"`
HeartbeatPeriod uint32 `json:"heartbeatPeriod"`
} }
// Build implements Buildable. // Build implements Buildable.
@@ -164,13 +163,15 @@ func (c *WebSocketConfig) Build() (proto.Message, error) {
path = u.String() path = u.String()
} }
} }
// If http host is not set in the Host field, but in headers field, we add it to Host Field here. // Priority (client): host > serverName > address
// If we don't do that, http host will be overwritten as address. for k, v := range c.Headers {
// Host priority: Host field > headers field > address. if strings.ToLower(k) == "host" {
if c.Host == "" && c.Headers["host"] != "" { errors.PrintDeprecatedFeatureWarning(`"host" in "headers"`, `independent "host"`)
c.Host = c.Headers["host"] if c.Host == "" {
} else if c.Host == "" && c.Headers["Host"] != "" { c.Host = v
c.Host = c.Headers["Host"] }
delete(c.Headers, k)
}
} }
config := &websocket.Config{ config := &websocket.Config{
Path: path, Path: path,
@@ -178,6 +179,7 @@ func (c *WebSocketConfig) Build() (proto.Message, error) {
Header: c.Headers, Header: c.Headers,
AcceptProxyProtocol: c.AcceptProxyProtocol, AcceptProxyProtocol: c.AcceptProxyProtocol,
Ed: ed, Ed: ed,
HeartbeatPeriod: c.HeartbeatPeriod,
} }
return config, nil return config, nil
} }
@@ -202,15 +204,11 @@ func (c *HttpUpgradeConfig) Build() (proto.Message, error) {
path = u.String() path = u.String()
} }
} }
// If http host is not set in the Host field, but in headers field, we add it to Host Field here. // Priority (client): host > serverName > address
// If we don't do that, http host will be overwritten as address. for k := range c.Headers {
// Host priority: Host field > headers field > address. if strings.ToLower(k) == "host" {
if c.Host == "" && c.Headers["host"] != "" { return nil, errors.New(`"headers" can't contain "host"`)
c.Host = c.Headers["host"] }
delete(c.Headers, "host")
} else if c.Host == "" && c.Headers["Host"] != "" {
c.Host = c.Headers["Host"]
delete(c.Headers, "Host")
} }
config := &httpupgrade.Config{ config := &httpupgrade.Config{
Path: path, Path: path,
@@ -225,32 +223,30 @@ func (c *HttpUpgradeConfig) Build() (proto.Message, error) {
type SplitHTTPConfig struct { type SplitHTTPConfig struct {
Host string `json:"host"` Host string `json:"host"`
Path string `json:"path"` Path string `json:"path"`
Mode string `json:"mode"`
Headers map[string]string `json:"headers"` Headers map[string]string `json:"headers"`
ScMaxConcurrentPosts *Int32Range `json:"scMaxConcurrentPosts"` XPaddingBytes Int32Range `json:"xPaddingBytes"`
ScMaxEachPostBytes *Int32Range `json:"scMaxEachPostBytes"` NoGRPCHeader bool `json:"noGRPCHeader"`
ScMinPostsIntervalMs *Int32Range `json:"scMinPostsIntervalMs"`
NoSSEHeader bool `json:"noSSEHeader"` NoSSEHeader bool `json:"noSSEHeader"`
XPaddingBytes *Int32Range `json:"xPaddingBytes"` ScMaxEachPostBytes Int32Range `json:"scMaxEachPostBytes"`
Xmux Xmux `json:"xmux"` ScMinPostsIntervalMs Int32Range `json:"scMinPostsIntervalMs"`
ScMaxBufferedPosts int64 `json:"scMaxBufferedPosts"`
Xmux XmuxConfig `json:"xmux"`
DownloadSettings *StreamConfig `json:"downloadSettings"` DownloadSettings *StreamConfig `json:"downloadSettings"`
Extra json.RawMessage `json:"extra"`
} }
type Xmux struct { type XmuxConfig struct {
MaxConcurrency *Int32Range `json:"maxConcurrency"` MaxConcurrency Int32Range `json:"maxConcurrency"`
MaxConnections *Int32Range `json:"maxConnections"` MaxConnections Int32Range `json:"maxConnections"`
CMaxReuseTimes *Int32Range `json:"cMaxReuseTimes"` CMaxReuseTimes Int32Range `json:"cMaxReuseTimes"`
CMaxLifetimeMs *Int32Range `json:"cMaxLifetimeMs"` HMaxRequestTimes Int32Range `json:"hMaxRequestTimes"`
HMaxReusableSecs Int32Range `json:"hMaxReusableSecs"`
HKeepAlivePeriod int64 `json:"hKeepAlivePeriod"`
} }
func splithttpNewRandRangeConfig(input *Int32Range) *splithttp.RandRangeConfig { func newRangeConfig(input Int32Range) *splithttp.RangeConfig {
if input == nil { return &splithttp.RangeConfig{
return &splithttp.RandRangeConfig{
From: 0,
To: 0,
}
}
return &splithttp.RandRangeConfig{
From: input.From, From: input.From,
To: input.To, To: input.To,
} }
@@ -258,99 +254,75 @@ func splithttpNewRandRangeConfig(input *Int32Range) *splithttp.RandRangeConfig {
// Build implements Buildable. // Build implements Buildable.
func (c *SplitHTTPConfig) Build() (proto.Message, error) { func (c *SplitHTTPConfig) Build() (proto.Message, error) {
// If http host is not set in the Host field, but in headers field, we add it to Host Field here. if c.Extra != nil {
// If we don't do that, http host will be overwritten as address. var extra SplitHTTPConfig
// Host priority: Host field > headers field > address. if err := json.Unmarshal(c.Extra, &extra); err != nil {
if c.Host == "" && c.Headers["host"] != "" { return nil, errors.New(`Failed to unmarshal "extra".`).Base(err)
c.Host = c.Headers["host"] }
} else if c.Host == "" && c.Headers["Host"] != "" { extra.Host = c.Host
c.Host = c.Headers["Host"] extra.Path = c.Path
extra.Mode = c.Mode
c = &extra
} }
if c.Xmux.MaxConnections != nil && c.Xmux.MaxConnections.To > 0 && c.Xmux.MaxConcurrency != nil && c.Xmux.MaxConcurrency.To > 0 { switch c.Mode {
case "":
c.Mode = "auto"
case "auto", "packet-up", "stream-up", "stream-one":
default:
return nil, errors.New("unsupported mode: " + c.Mode)
}
// Priority (client): host > serverName > address
for k := range c.Headers {
if strings.ToLower(k) == "host" {
return nil, errors.New(`"headers" can't contain "host"`)
}
}
if c.Xmux.MaxConnections.To > 0 && c.Xmux.MaxConcurrency.To > 0 {
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency") return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
} }
if c.Xmux == (XmuxConfig{}) {
// Multiplexing config c.Xmux.MaxConcurrency.From = 16
muxProtobuf := splithttp.Multiplexing{ c.Xmux.MaxConcurrency.To = 32
MaxConcurrency: splithttpNewRandRangeConfig(c.Xmux.MaxConcurrency), c.Xmux.HMaxRequestTimes.From = 600
MaxConnections: splithttpNewRandRangeConfig(c.Xmux.MaxConnections), c.Xmux.HMaxRequestTimes.To = 900
CMaxReuseTimes: splithttpNewRandRangeConfig(c.Xmux.CMaxReuseTimes), c.Xmux.HMaxReusableSecs.From = 1800
CMaxLifetimeMs: splithttpNewRandRangeConfig(c.Xmux.CMaxLifetimeMs), c.Xmux.HMaxReusableSecs.To = 3000
}
if muxProtobuf.MaxConcurrency.To == 0 &&
muxProtobuf.MaxConnections.To == 0 &&
muxProtobuf.CMaxReuseTimes.To == 0 &&
muxProtobuf.CMaxLifetimeMs.To == 0 {
muxProtobuf.MaxConcurrency.From = 16
muxProtobuf.MaxConcurrency.To = 32
muxProtobuf.CMaxReuseTimes.From = 64
muxProtobuf.CMaxReuseTimes.To = 128
} }
config := &splithttp.Config{ config := &splithttp.Config{
Path: c.Path,
Host: c.Host, Host: c.Host,
Header: c.Headers, Path: c.Path,
ScMaxConcurrentPosts: splithttpNewRandRangeConfig(c.ScMaxConcurrentPosts), Mode: c.Mode,
ScMaxEachPostBytes: splithttpNewRandRangeConfig(c.ScMaxEachPostBytes), Headers: c.Headers,
ScMinPostsIntervalMs: splithttpNewRandRangeConfig(c.ScMinPostsIntervalMs), XPaddingBytes: newRangeConfig(c.XPaddingBytes),
NoGRPCHeader: c.NoGRPCHeader,
NoSSEHeader: c.NoSSEHeader, NoSSEHeader: c.NoSSEHeader,
XPaddingBytes: splithttpNewRandRangeConfig(c.XPaddingBytes), ScMaxEachPostBytes: newRangeConfig(c.ScMaxEachPostBytes),
Xmux: &muxProtobuf, ScMinPostsIntervalMs: newRangeConfig(c.ScMinPostsIntervalMs),
ScMaxBufferedPosts: c.ScMaxBufferedPosts,
Xmux: &splithttp.XmuxConfig{
MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency),
MaxConnections: newRangeConfig(c.Xmux.MaxConnections),
CMaxReuseTimes: newRangeConfig(c.Xmux.CMaxReuseTimes),
HMaxRequestTimes: newRangeConfig(c.Xmux.HMaxRequestTimes),
HMaxReusableSecs: newRangeConfig(c.Xmux.HMaxReusableSecs),
HKeepAlivePeriod: c.Xmux.HKeepAlivePeriod,
},
} }
var err error
if c.DownloadSettings != nil { if c.DownloadSettings != nil {
if c.Mode == "stream-one" {
return nil, errors.New(`Can not use "downloadSettings" in "stream-one" mode.`)
}
var err error
if config.DownloadSettings, err = c.DownloadSettings.Build(); err != nil { if config.DownloadSettings, err = c.DownloadSettings.Build(); err != nil {
return nil, errors.New(`Failed to build "downloadSettings".`).Base(err) return nil, errors.New(`Failed to build "downloadSettings".`).Base(err)
} }
} }
return config, nil
}
type HTTPConfig struct {
Host *StringList `json:"host"`
Path string `json:"path"`
ReadIdleTimeout int32 `json:"read_idle_timeout"`
HealthCheckTimeout int32 `json:"health_check_timeout"`
Method string `json:"method"`
Headers map[string]*StringList `json:"headers"`
}
// Build implements Buildable.
func (c *HTTPConfig) Build() (proto.Message, error) {
if c.ReadIdleTimeout <= 0 {
c.ReadIdleTimeout = 0
}
if c.HealthCheckTimeout <= 0 {
c.HealthCheckTimeout = 0
}
config := &http.Config{
Path: c.Path,
IdleTimeout: c.ReadIdleTimeout,
HealthCheckTimeout: c.HealthCheckTimeout,
}
if c.Host != nil {
config.Host = []string(*c.Host)
}
if c.Method != "" {
config.Method = c.Method
}
if len(c.Headers) > 0 {
config.Header = make([]*httpheader.Header, 0, len(c.Headers))
headerNames := sortMapKeys(c.Headers)
for _, key := range headerNames {
value := c.Headers[key]
if value == nil {
return nil, errors.New("empty HTTP header value: " + key).AtError()
}
config.Header = append(config.Header, &httpheader.Header{
Name: key,
Value: append([]string(nil), (*value)...),
})
}
}
return config, nil return config, nil
} }
@@ -430,6 +402,7 @@ type TLSConfig struct {
RejectUnknownSNI bool `json:"rejectUnknownSni"` RejectUnknownSNI bool `json:"rejectUnknownSni"`
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"` PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"` PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"`
CurvePreferences *StringList `json:"curvePreferences"`
MasterKeyLog string `json:"masterKeyLog"` MasterKeyLog string `json:"masterKeyLog"`
} }
@@ -452,13 +425,16 @@ func (c *TLSConfig) Build() (proto.Message, error) {
if c.ALPN != nil && len(*c.ALPN) > 0 { if c.ALPN != nil && len(*c.ALPN) > 0 {
config.NextProtocol = []string(*c.ALPN) config.NextProtocol = []string(*c.ALPN)
} }
if c.CurvePreferences != nil && len(*c.CurvePreferences) > 0 {
config.CurvePreferences = []string(*c.CurvePreferences)
}
config.EnableSessionResumption = c.EnableSessionResumption config.EnableSessionResumption = c.EnableSessionResumption
config.DisableSystemRoot = c.DisableSystemRoot config.DisableSystemRoot = c.DisableSystemRoot
config.MinVersion = c.MinVersion config.MinVersion = c.MinVersion
config.MaxVersion = c.MaxVersion config.MaxVersion = c.MaxVersion
config.CipherSuites = c.CipherSuites config.CipherSuites = c.CipherSuites
config.Fingerprint = strings.ToLower(c.Fingerprint) config.Fingerprint = strings.ToLower(c.Fingerprint)
if config.Fingerprint != "" && tls.GetFingerprint(config.Fingerprint) == nil { if config.Fingerprint != "unsafe" && tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown fingerprint: `, config.Fingerprint) return nil, errors.New(`unknown fingerprint: `, config.Fingerprint)
} }
config.RejectUnknownSni = c.RejectUnknownSNI config.RejectUnknownSni = c.RejectUnknownSNI
@@ -568,7 +544,7 @@ func (c *REALITYConfig) Build() (proto.Message, error) {
return nil, errors.New(`invalid "minClientVer": `, c.MinClientVer) return nil, errors.New(`invalid "minClientVer": `, c.MinClientVer)
} }
if u, err = strconv.ParseUint(s, 10, 8); err != nil { if u, err = strconv.ParseUint(s, 10, 8); err != nil {
return nil, errors.New(`"minClientVer[`, i, `]" should be lesser than 256`) return nil, errors.New(`"minClientVer[`, i, `]" should be less than 256`)
} else { } else {
config.MinClientVer[i] = byte(u) config.MinClientVer[i] = byte(u)
} }
@@ -582,7 +558,7 @@ func (c *REALITYConfig) Build() (proto.Message, error) {
return nil, errors.New(`invalid "maxClientVer": `, c.MaxClientVer) return nil, errors.New(`invalid "maxClientVer": `, c.MaxClientVer)
} }
if u, err = strconv.ParseUint(s, 10, 8); err != nil { if u, err = strconv.ParseUint(s, 10, 8); err != nil {
return nil, errors.New(`"maxClientVer[`, i, `]" should be lesser than 256`) return nil, errors.New(`"maxClientVer[`, i, `]" should be less than 256`)
} else { } else {
config.MaxClientVer[i] = byte(u) config.MaxClientVer[i] = byte(u)
} }
@@ -604,15 +580,13 @@ func (c *REALITYConfig) Build() (proto.Message, error) {
config.ServerNames = c.ServerNames config.ServerNames = c.ServerNames
config.MaxTimeDiff = c.MaxTimeDiff config.MaxTimeDiff = c.MaxTimeDiff
} else { } else {
if c.Fingerprint == "" { config.Fingerprint = strings.ToLower(c.Fingerprint)
return nil, errors.New(`empty "fingerprint"`) if config.Fingerprint == "unsafe" || config.Fingerprint == "hellogolang" {
}
if config.Fingerprint = strings.ToLower(c.Fingerprint); tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint)
}
if config.Fingerprint == "hellogolang" {
return nil, errors.New(`invalid "fingerprint": `, config.Fingerprint) return nil, errors.New(`invalid "fingerprint": `, config.Fingerprint)
} }
if tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint)
}
if len(c.ServerNames) != 0 { if len(c.ServerNames) != 0 {
return nil, errors.New(`non-empty "serverNames", please use "serverName" instead`) return nil, errors.New(`non-empty "serverNames", please use "serverName" instead`)
} }
@@ -670,18 +644,23 @@ func (p TransportProtocol) Build() (string, error) {
switch strings.ToLower(string(p)) { switch strings.ToLower(string(p)) {
case "raw", "tcp": case "raw", "tcp":
return "tcp", nil return "tcp", nil
case "kcp", "mkcp":
return "mkcp", nil
case "ws", "websocket":
return "websocket", nil
case "h2", "h3", "http":
return "http", nil
case "grpc":
return "grpc", nil
case "httpupgrade":
return "httpupgrade", nil
case "xhttp", "splithttp": case "xhttp", "splithttp":
return "splithttp", nil return "splithttp", nil
case "kcp", "mkcp":
return "mkcp", nil
case "grpc":
errors.PrintDeprecatedFeatureWarning("gRPC transport (with unnecessary costs, etc.)", "XHTTP stream-up H2")
return "grpc", nil
case "ws", "websocket":
errors.PrintDeprecatedFeatureWarning("WebSocket transport (with ALPN http/1.1, etc.)", "XHTTP H2 & H3")
return "websocket", nil
case "httpupgrade":
errors.PrintDeprecatedFeatureWarning("HTTPUpgrade transport (with ALPN http/1.1, etc.)", "XHTTP H2 & H3")
return "httpupgrade", nil
case "h2", "h3", "http":
return "", errors.PrintRemovedFeatureError("HTTP transport (without header padding, etc.)", "XHTTP stream-one H2 & H3")
case "quic":
return "", errors.PrintRemovedFeatureError("QUIC transport (without web service, etc.)", "XHTTP stream-one H3")
default: default:
return "", errors.New("Config: unknown transport protocol: ", p) return "", errors.New("Config: unknown transport protocol: ", p)
} }
@@ -706,7 +685,7 @@ type SocketConfig struct {
TCPCongestion string `json:"tcpCongestion"` TCPCongestion string `json:"tcpCongestion"`
TCPWindowClamp int32 `json:"tcpWindowClamp"` TCPWindowClamp int32 `json:"tcpWindowClamp"`
TCPMaxSeg int32 `json:"tcpMaxSeg"` TCPMaxSeg int32 `json:"tcpMaxSeg"`
TcpNoDelay bool `json:"tcpNoDelay"` Penetrate bool `json:"penetrate"`
TCPUserTimeout int32 `json:"tcpUserTimeout"` TCPUserTimeout int32 `json:"tcpUserTimeout"`
V6only bool `json:"v6only"` V6only bool `json:"v6only"`
Interface string `json:"interface"` Interface string `json:"interface"`
@@ -793,7 +772,7 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
TcpCongestion: c.TCPCongestion, TcpCongestion: c.TCPCongestion,
TcpWindowClamp: c.TCPWindowClamp, TcpWindowClamp: c.TCPWindowClamp,
TcpMaxSeg: c.TCPMaxSeg, TcpMaxSeg: c.TCPMaxSeg,
TcpNoDelay: c.TcpNoDelay, Penetrate: c.Penetrate,
TcpUserTimeout: c.TCPUserTimeout, TcpUserTimeout: c.TCPUserTimeout,
V6Only: c.V6only, V6Only: c.V6only,
Interface: c.Interface, Interface: c.Interface,
@@ -811,14 +790,13 @@ type StreamConfig struct {
REALITYSettings *REALITYConfig `json:"realitySettings"` REALITYSettings *REALITYConfig `json:"realitySettings"`
RAWSettings *TCPConfig `json:"rawSettings"` RAWSettings *TCPConfig `json:"rawSettings"`
TCPSettings *TCPConfig `json:"tcpSettings"` TCPSettings *TCPConfig `json:"tcpSettings"`
KCPSettings *KCPConfig `json:"kcpSettings"`
WSSettings *WebSocketConfig `json:"wsSettings"`
HTTPSettings *HTTPConfig `json:"httpSettings"`
SocketSettings *SocketConfig `json:"sockopt"`
GRPCConfig *GRPCConfig `json:"grpcSettings"`
HTTPUPGRADESettings *HttpUpgradeConfig `json:"httpupgradeSettings"`
XHTTPSettings *SplitHTTPConfig `json:"xhttpSettings"` XHTTPSettings *SplitHTTPConfig `json:"xhttpSettings"`
SplitHTTPSettings *SplitHTTPConfig `json:"splithttpSettings"` SplitHTTPSettings *SplitHTTPConfig `json:"splithttpSettings"`
KCPSettings *KCPConfig `json:"kcpSettings"`
GRPCSettings *GRPCConfig `json:"grpcSettings"`
WSSettings *WebSocketConfig `json:"wsSettings"`
HTTPUPGRADESettings *HttpUpgradeConfig `json:"httpupgradeSettings"`
SocketSettings *SocketConfig `json:"sockopt"`
} }
// Build implements Buildable. // Build implements Buildable.
@@ -852,8 +830,8 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
config.SecuritySettings = append(config.SecuritySettings, tm) config.SecuritySettings = append(config.SecuritySettings, tm)
config.SecurityType = tm.Type config.SecurityType = tm.Type
case "reality": case "reality":
if config.ProtocolName != "tcp" && config.ProtocolName != "http" && config.ProtocolName != "grpc" && config.ProtocolName != "splithttp" { if config.ProtocolName != "tcp" && config.ProtocolName != "splithttp" && config.ProtocolName != "grpc" {
return nil, errors.New("REALITY only supports RAW, H2, gRPC and XHTTP for now.") return nil, errors.New("REALITY only supports RAW, XHTTP and gRPC for now.")
} }
if c.REALITYSettings == nil { if c.REALITYSettings == nil {
return nil, errors.New(`REALITY: Empty "realitySettings".`) return nil, errors.New(`REALITY: Empty "realitySettings".`)
@@ -883,56 +861,6 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
Settings: serial.ToTypedMessage(ts), Settings: serial.ToTypedMessage(ts),
}) })
} }
if c.KCPSettings != nil {
ts, err := c.KCPSettings.Build()
if err != nil {
return nil, errors.New("Failed to build mKCP config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "mkcp",
Settings: serial.ToTypedMessage(ts),
})
}
if c.WSSettings != nil {
ts, err := c.WSSettings.Build()
if err != nil {
return nil, errors.New("Failed to build WebSocket config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "websocket",
Settings: serial.ToTypedMessage(ts),
})
}
if c.HTTPSettings != nil {
ts, err := c.HTTPSettings.Build()
if err != nil {
return nil, errors.New("Failed to build HTTP config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "http",
Settings: serial.ToTypedMessage(ts),
})
}
if c.GRPCConfig != nil {
gs, err := c.GRPCConfig.Build()
if err != nil {
return nil, errors.New("Failed to build gRPC config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "grpc",
Settings: serial.ToTypedMessage(gs),
})
}
if c.HTTPUPGRADESettings != nil {
hs, err := c.HTTPUPGRADESettings.Build()
if err != nil {
return nil, errors.New("Failed to build HttpUpgrade config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "httpupgrade",
Settings: serial.ToTypedMessage(hs),
})
}
if c.XHTTPSettings != nil { if c.XHTTPSettings != nil {
c.SplitHTTPSettings = c.XHTTPSettings c.SplitHTTPSettings = c.XHTTPSettings
} }
@@ -946,10 +874,50 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
Settings: serial.ToTypedMessage(hs), Settings: serial.ToTypedMessage(hs),
}) })
} }
if c.KCPSettings != nil {
ts, err := c.KCPSettings.Build()
if err != nil {
return nil, errors.New("Failed to build mKCP config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "mkcp",
Settings: serial.ToTypedMessage(ts),
})
}
if c.GRPCSettings != nil {
gs, err := c.GRPCSettings.Build()
if err != nil {
return nil, errors.New("Failed to build gRPC config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "grpc",
Settings: serial.ToTypedMessage(gs),
})
}
if c.WSSettings != nil {
ts, err := c.WSSettings.Build()
if err != nil {
return nil, errors.New("Failed to build WebSocket config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "websocket",
Settings: serial.ToTypedMessage(ts),
})
}
if c.HTTPUPGRADESettings != nil {
hs, err := c.HTTPUPGRADESettings.Build()
if err != nil {
return nil, errors.New("Failed to build HTTPUpgrade config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "httpupgrade",
Settings: serial.ToTypedMessage(hs),
})
}
if c.SocketSettings != nil { if c.SocketSettings != nil {
ss, err := c.SocketSettings.Build() ss, err := c.SocketSettings.Build()
if err != nil { if err != nil {
return nil, errors.New("Failed to build sockopt").Base(err) return nil, errors.New("Failed to build sockopt.").Base(err)
} }
config.SocketSettings = ss config.SocketSettings = ss
} }

View File

@@ -24,6 +24,7 @@ var (
"dokodemo-door": func() interface{} { return new(DokodemoConfig) }, "dokodemo-door": func() interface{} { return new(DokodemoConfig) },
"http": func() interface{} { return new(HTTPServerConfig) }, "http": func() interface{} { return new(HTTPServerConfig) },
"shadowsocks": func() interface{} { return new(ShadowsocksServerConfig) }, "shadowsocks": func() interface{} { return new(ShadowsocksServerConfig) },
"mixed": func() interface{} { return new(SocksServerConfig) },
"socks": func() interface{} { return new(SocksServerConfig) }, "socks": func() interface{} { return new(SocksServerConfig) },
"vless": func() interface{} { return new(VLessInboundConfig) }, "vless": func() interface{} { return new(VLessInboundConfig) },
"vmess": func() interface{} { return new(VMessInboundConfig) }, "vmess": func() interface{} { return new(VMessInboundConfig) },
@@ -363,7 +364,7 @@ func (c *StatsConfig) Build() (*stats.Config, error) {
type Config struct { type Config struct {
// Deprecated: Global transport config is no longer used // Deprecated: Global transport config is no longer used
// left for returning error // left for returning error
Transport map[string]json.RawMessage `json:"transport"` Transport map[string]json.RawMessage `json:"transport"`
LogConfig *LogConfig `json:"log"` LogConfig *LogConfig `json:"log"`
RouterConfig *RouterConfig `json:"routing"` RouterConfig *RouterConfig `json:"routing"`

View File

@@ -48,9 +48,7 @@ func TestXrayConfig(t *testing.T) {
"streamSettings": { "streamSettings": {
"network": "ws", "network": "ws",
"wsSettings": { "wsSettings": {
"headers": { "host": "example.domain",
"host": "example.domain"
},
"path": "" "path": ""
}, },
"tlsSettings": { "tlsSettings": {
@@ -139,9 +137,6 @@ func TestXrayConfig(t *testing.T) {
ProtocolName: "websocket", ProtocolName: "websocket",
Settings: serial.ToTypedMessage(&websocket.Config{ Settings: serial.ToTypedMessage(&websocket.Config{
Host: "example.domain", Host: "example.domain",
Header: map[string]string{
"host": "example.domain",
},
}), }),
}, },
}, },

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"go/build" "go/build"
@@ -18,7 +19,7 @@ var directory = flag.String("pwd", "", "Working directory of Xray vformat.")
func envFile() (string, error) { func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" { if file := os.Getenv("GOENV"); file != "" {
if file == "off" { if file == "off" {
return "", fmt.Errorf("GOENV=off") return "", errors.New("GOENV=off")
} }
return file, nil return file, nil
} }
@@ -27,7 +28,7 @@ func envFile() (string, error) {
return "", err return "", err
} }
if dir == "" { if dir == "" {
return "", fmt.Errorf("missing user-config dir") return "", errors.New("missing user-config dir")
} }
return filepath.Join(dir, "go", "env"), nil return filepath.Join(dir, "go", "env"), nil
} }
@@ -40,7 +41,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err return "", err
} }
if file == "" { if file == "" {
return "", fmt.Errorf("missing runtime env file") return "", errors.New("missing runtime env file")
} }
var data []byte var data []byte
var runtimeEnv string var runtimeEnv string

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"go/build" "go/build"
@@ -22,7 +23,7 @@ var directory = flag.String("pwd", "", "Working directory of Xray vprotogen.")
func envFile() (string, error) { func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" { if file := os.Getenv("GOENV"); file != "" {
if file == "off" { if file == "off" {
return "", fmt.Errorf("GOENV=off") return "", errors.New("GOENV=off")
} }
return file, nil return file, nil
} }
@@ -31,7 +32,7 @@ func envFile() (string, error) {
return "", err return "", err
} }
if dir == "" { if dir == "" {
return "", fmt.Errorf("missing user-config dir") return "", errors.New("missing user-config dir")
} }
return filepath.Join(dir, "go", "env"), nil return filepath.Join(dir, "go", "env"), nil
} }
@@ -44,7 +45,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err return "", err
} }
if file == "" { if file == "" {
return "", fmt.Errorf("missing runtime env file") return "", errors.New("missing runtime env file")
} }
var data []byte var data []byte
var runtimeEnv string var runtimeEnv string
@@ -101,12 +102,12 @@ Download %s v%s or later from https://github.com/protocolbuffers/protobuf/releas
func getProjectProtocVersion(url string) (string, error) { func getProjectProtocVersion(url string) (string, error) {
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
return "", fmt.Errorf("can not get the version of protobuf used in xray project") return "", errors.New("can not get the version of protobuf used in xray project")
} }
defer resp.Body.Close() defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return "", fmt.Errorf("can not read from body") return "", errors.New("can not read from body")
} }
versionRegexp := regexp.MustCompile(`\/\/\s*protoc\s*v\d+\.(\d+\.\d+)`) versionRegexp := regexp.MustCompile(`\/\/\s*protoc\s*v\d+\.(\d+\.\d+)`)
matched := versionRegexp.FindStringSubmatch(string(body)) matched := versionRegexp.FindStringSubmatch(string(body))

View File

@@ -39,7 +39,7 @@ func executeInboundUser(cmd *base.Command, args []string) {
client := handlerService.NewHandlerServiceClient(conn) client := handlerService.NewHandlerServiceClient(conn)
r := &handlerService.GetInboundUserRequest{ r := &handlerService.GetInboundUserRequest{
Tag: tag, Tag: tag,
Email: email, Email: email,
} }
resp, err := client.GetInboundUsers(ctx, r) resp, err := client.GetInboundUsers(ctx, r)

View File

@@ -3,6 +3,7 @@ package api
import ( import (
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@@ -15,8 +16,8 @@ import (
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/main/commands/base"
creflect "github.com/xtls/xray-core/common/reflect" creflect "github.com/xtls/xray-core/common/reflect"
"github.com/xtls/xray-core/main/commands/base"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -101,7 +102,7 @@ func fetchHTTPContent(target string) ([]byte, error) {
content, err := buf.ReadAllToBytes(resp.Body) content, err := buf.ReadAllToBytes(resp.Body)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read HTTP response") return nil, errors.New("failed to read HTTP response")
} }
return content, nil return content, nil

View File

@@ -51,7 +51,6 @@ import (
// Transports // Transports
_ "github.com/xtls/xray-core/transport/internet/grpc" _ "github.com/xtls/xray-core/transport/internet/grpc"
_ "github.com/xtls/xray-core/transport/internet/http"
_ "github.com/xtls/xray-core/transport/internet/httpupgrade" _ "github.com/xtls/xray-core/transport/internet/httpupgrade"
_ "github.com/xtls/xray-core/transport/internet/kcp" _ "github.com/xtls/xray-core/transport/internet/kcp"
_ "github.com/xtls/xray-core/transport/internet/reality" _ "github.com/xtls/xray-core/transport/internet/reality"

View File

@@ -30,9 +30,9 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
// Process implements OutboundHandler.Dispatch(). // Process implements OutboundHandler.Dispatch().
func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error { func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
ob.Name = "blackhole" ob.Name = "blackhole"
nBytes := h.response.WriteTo(link.Writer) nBytes := h.response.WriteTo(link.Writer)
if nBytes > 0 { if nBytes > 0 {
// Sleep a little here to make sure the response is sent to client. // Sleep a little here to make sure the response is sent to client.

View File

@@ -17,7 +17,7 @@ Content-Length: 0
// ResponseConfig is the configuration for blackhole responses. // ResponseConfig is the configuration for blackhole responses.
type ResponseConfig interface { type ResponseConfig interface {
// WriteTo writes predefined response to the give buffer. // WriteTo writes a predefined response to the specified buffer.
WriteTo(buf.Writer) int32 WriteTo(buf.Writer) int32
} }

View File

@@ -27,7 +27,7 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
h := new(Handler) h := new(Handler)
if err := core.RequireFeatures(ctx, func(dnsClient dns.Client, policyManager policy.Manager) error { if err := core.RequireFeatures(ctx, func(dnsClient dns.Client, policyManager policy.Manager) error {
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
h.fdns = fdns h.fdns = fdns
}) })
return h.Init(config.(*Config), dnsClient, policyManager) return h.Init(config.(*Config), dnsClient, policyManager)
@@ -49,7 +49,7 @@ type Handler struct {
server net.Destination server net.Destination
timeout time.Duration timeout time.Duration
nonIPQuery string nonIPQuery string
blockTypes []int32 blockTypes []int32
} }
func (h *Handler) Init(config *Config, dnsClient dns.Client, policyManager policy.Manager) error { func (h *Handler) Init(config *Config, dnsClient dns.Client, policyManager policy.Manager) error {

View File

@@ -2,6 +2,7 @@ package dokodemo
import ( import (
"context" "context"
"runtime"
"sync/atomic" "sync/atomic"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -147,10 +148,6 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
return nil return nil
} }
tproxyRequest := func() error {
return nil
}
var writer buf.Writer var writer buf.Writer
if network == net.Network_TCP { if network == net.Network_TCP {
writer = buf.NewWriter(conn) writer = buf.NewWriter(conn)
@@ -180,7 +177,12 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
return err return err
} }
writer = NewPacketWriter(pConn, &dest, mark, back) writer = NewPacketWriter(pConn, &dest, mark, back)
defer writer.(*PacketWriter).Close() defer func() {
runtime.Gosched()
common.Interrupt(link.Reader) // maybe duplicated
runtime.Gosched()
writer.(*PacketWriter).Close() // close fake UDP conns
}()
/* /*
sockopt := &internet.SocketConfig{ sockopt := &internet.SocketConfig{
Tproxy: internet.SocketConfig_TProxy, Tproxy: internet.SocketConfig_TProxy,
@@ -219,17 +221,24 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
responseDone := func() error { responseDone := func() error {
defer timer.SetTimeout(plcy.Timeouts.UplinkOnly) defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
if network == net.Network_UDP && destinationOverridden {
buf.Copy(link.Reader, writer) // respect upload's timeout
return nil
}
if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil { if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to transport response").Base(err) return errors.New("failed to transport response").Base(err)
} }
return nil return nil
} }
if err := task.Run(ctx, task.OnSuccess(func() error { if err := task.Run(ctx,
return task.Run(ctx, requestDone, tproxyRequest) task.OnSuccess(func() error { return task.Run(ctx, requestDone) }, task.Close(link.Writer)),
}, task.Close(link.Writer)), responseDone); err != nil { responseDone); err != nil {
common.Interrupt(link.Reader) runtime.Gosched()
common.Interrupt(link.Writer) common.Interrupt(link.Writer)
runtime.Gosched()
common.Interrupt(link.Reader)
return errors.New("connection ends").Base(err) return errors.New("connection ends").Base(err)
} }

View File

@@ -78,7 +78,7 @@ type UserManager interface {
// RemoveUser removes a user by email. // RemoveUser removes a user by email.
RemoveUser(context.Context, string) error RemoveUser(context.Context, string) error
// Get user by email. // Get user by email.
GetUser(context.Context, string) *protocol.MemoryUser GetUser(context.Context, string) *protocol.MemoryUser

View File

@@ -22,7 +22,7 @@ import (
// MemoryAccount is an account type converted from Account. // MemoryAccount is an account type converted from Account.
type MemoryAccount struct { type MemoryAccount struct {
Cipher Cipher Cipher Cipher
CipherType CipherType CipherType CipherType
Key []byte Key []byte
Password string Password string
@@ -42,8 +42,8 @@ func (a *MemoryAccount) Equals(another protocol.Account) bool {
func (a *MemoryAccount) ToProto() proto.Message { func (a *MemoryAccount) ToProto() proto.Message {
return &Account{ return &Account{
CipherType: a.CipherType, CipherType: a.CipherType,
Password: a.Password, Password: a.Password,
IvCheck: a.replayFilter != nil, IvCheck: a.replayFilter != nil,
} }
} }
@@ -117,10 +117,10 @@ func (a *Account) AsAccount() (protocol.Account, error) {
return nil, errors.New("failed to get cipher").Base(err) return nil, errors.New("failed to get cipher").Base(err)
} }
return &MemoryAccount{ return &MemoryAccount{
Cipher: Cipher, Cipher: Cipher,
CipherType: a.CipherType, CipherType: a.CipherType,
Key: passwordToCipherKey([]byte(a.Password), Cipher.KeySize()), Key: passwordToCipherKey([]byte(a.Password), Cipher.KeySize()),
Password: a.Password, Password: a.Password,
replayFilter: func() antireplay.GeneralizedReplayFilter { replayFilter: func() antireplay.GeneralizedReplayFilter {
if a.IvCheck { if a.IvCheck {
return antireplay.NewBloomRing() return antireplay.NewBloomRing()

View File

@@ -10,9 +10,9 @@ 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/crypto" "github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/drain" "github.com/xtls/xray-core/common/drain"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
) )

View File

@@ -8,13 +8,13 @@ import (
// MemoryAccount is an account type converted from Account. // MemoryAccount is an account type converted from Account.
type MemoryAccount struct { type MemoryAccount struct {
Key string Key string
} }
// AsAccount implements protocol.AsAccount. // AsAccount implements protocol.AsAccount.
func (u *Account) AsAccount() (protocol.Account, error) { func (u *Account) AsAccount() (protocol.Account, error) {
return &MemoryAccount{ return &MemoryAccount{
Key: u.GetKey(), Key: u.GetKey(),
}, nil }, nil
} }

View File

@@ -155,7 +155,7 @@ func (i *MultiUserInbound) GetUser(ctx context.Context, email string) *protocol.
if email == "" { if email == "" {
return nil return nil
} }
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()

View File

@@ -45,7 +45,7 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
serverPicker: protocol.NewRoundRobinServerPicker(serverList), serverPicker: protocol.NewRoundRobinServerPicker(serverList),
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
} }
return c, nil return c, nil
} }

View File

@@ -361,14 +361,14 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
cs := tlsConn.ConnectionState() cs := tlsConn.ConnectionState()
name = cs.ServerName name = cs.ServerName
alpn = cs.NegotiatedProtocol alpn = cs.NegotiatedProtocol
errors.LogInfo(ctx, "realName = " + name) errors.LogInfo(ctx, "realName = "+name)
errors.LogInfo(ctx, "realAlpn = " + alpn) errors.LogInfo(ctx, "realAlpn = "+alpn)
} else if realityConn, ok := iConn.(*reality.Conn); ok { } else if realityConn, ok := iConn.(*reality.Conn); ok {
cs := realityConn.ConnectionState() cs := realityConn.ConnectionState()
name = cs.ServerName name = cs.ServerName
alpn = cs.NegotiatedProtocol alpn = cs.NegotiatedProtocol
errors.LogInfo(ctx, "realName = " + name) errors.LogInfo(ctx, "realName = "+name)
errors.LogInfo(ctx, "realAlpn = " + alpn) errors.LogInfo(ctx, "realAlpn = "+alpn)
} }
name = strings.ToLower(name) name = strings.ToLower(name)
alpn = strings.ToLower(alpn) alpn = strings.ToLower(alpn)
@@ -418,7 +418,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
} }
if k == '?' || k == ' ' { if k == '?' || k == ' ' {
path = string(firstBytes[i:j]) path = string(firstBytes[i:j])
errors.LogInfo(ctx, "realPath = " + path) errors.LogInfo(ctx, "realPath = "+path)
if pfb[path] == nil { if pfb[path] == nil {
path = "" path = ""
} }

View File

@@ -51,7 +51,6 @@ func (v *Validator) Get(hash string) *protocol.MemoryUser {
return nil return nil
} }
// Get a trojan user with hashed key, nil if user doesn't exist. // Get a trojan user with hashed key, nil if user doesn't exist.
func (v *Validator) GetByEmail(email string) *protocol.MemoryUser { func (v *Validator) GetByEmail(email string) *protocol.MemoryUser {
u, _ := v.email.Load(email) u, _ := v.email.Load(email)

View File

@@ -42,8 +42,8 @@ func (a *MemoryAccount) Equals(account protocol.Account) bool {
func (a *MemoryAccount) ToProto() proto.Message { func (a *MemoryAccount) ToProto() proto.Message {
return &Account{ return &Account{
Id: a.ID.String(), Id: a.ID.String(),
Flow: a.Flow, Flow: a.Flow,
Encryption: a.Encryption, Encryption: a.Encryption,
} }
} }

View File

@@ -491,12 +491,12 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset)) rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
} }
} else { } else {
return errors.New(account.ID.String() + " is not able to use " + requestAddons.Flow).AtWarning() return errors.New("account " + account.ID.String() + " is not able to use the flow " + requestAddons.Flow).AtWarning()
} }
case "": case "":
inbound.CanSpliceCopy = 3 inbound.CanSpliceCopy = 3
if account.Flow == vless.XRV && (request.Command == protocol.RequestCommandTCP || isMuxAndNotXUDP(request, first)) { if account.Flow == vless.XRV && (request.Command == protocol.RequestCommandTCP || isMuxAndNotXUDP(request, first)) {
return errors.New(account.ID.String() + " is not able to use \"\". Note that the pure TLS proxy has certain TLS in TLS characters.").AtWarning() return errors.New("account " + account.ID.String() + " is rejected since the client flow is empty. Note that the pure TLS proxy has certain TLS in TLS characters.").AtWarning()
} }
default: default:
return errors.New("unknown request flow " + requestAddons.Flow).AtWarning() return errors.New("unknown request flow " + requestAddons.Flow).AtWarning()

View File

@@ -38,8 +38,8 @@ func (a *MemoryAccount) ToProto() proto.Message {
test = test + "NoTerminationSignal" test = test + "NoTerminationSignal"
} }
return &Account{ return &Account{
Id: a.ID.String(), Id: a.ID.String(),
TestsEnabled: test, TestsEnabled: test,
SecuritySettings: &protocol.SecurityConfig{Type: a.Security}, SecuritySettings: &protocol.SecurityConfig{Type: a.Security},
} }
} }

View File

@@ -81,7 +81,7 @@ func (v *TimedUserValidator) GetAEAD(userHash []byte) (*protocol.MemoryUser, boo
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
return userd.(*protocol.MemoryUser), true, err return userd.(*protocol.MemoryUser), true, nil
} }
func (v *TimedUserValidator) Remove(email string) bool { func (v *TimedUserValidator) Remove(email string) bool {

View File

@@ -29,8 +29,8 @@ 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/dice" "github.com/xtls/xray-core/common/dice"
"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" "github.com/xtls/xray-core/common/protocol"

View File

@@ -147,12 +147,18 @@ func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) {
if s.info.inboundTag != nil { if s.info.inboundTag != nil {
ctx = session.ContextWithInbound(ctx, s.info.inboundTag) ctx = session.ContextWithInbound(ctx, s.info.inboundTag)
} }
if s.info.outboundTag != nil {
ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{s.info.outboundTag}) // what's this?
} // Session information should not be shared between different connections
if s.info.contentTag != nil { // why reuse them in server level? This will cause incorrect destoverride and unexpected routing behavior.
ctx = session.ContextWithContent(ctx, s.info.contentTag) // Disable it temporarily. Maybe s.info should be removed.
}
// if s.info.outboundTag != nil {
// ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{s.info.outboundTag})
// }
// if s.info.contentTag != nil {
// ctx = session.ContextWithContent(ctx, s.info.contentTag)
// }
link, err := s.info.dispatcher.Dispatch(ctx, dest) link, err := s.info.dispatcher.Dispatch(ctx, dest)
if err != nil { if err != nil {

View File

@@ -4,16 +4,18 @@ package wireguard
import ( import (
"context" "context"
"errors" goerrors "errors"
"fmt" "fmt"
"net" "net"
"net/netip" "net/netip"
"os" "os"
"sync"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"github.com/sagernet/sing/common/control" "github.com/sagernet/sing/common/control"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"github.com/xtls/xray-core/common/errors"
wgtun "golang.zx2c4.com/wireguard/tun" wgtun "golang.zx2c4.com/wireguard/tun"
) )
@@ -27,6 +29,23 @@ type deviceNet struct {
rules []*netlink.Rule rules []*netlink.Rule
} }
var (
tableIndex int = 10230
mu sync.Mutex
)
func allocateIPv6TableIndex() int {
mu.Lock()
defer mu.Unlock()
if tableIndex > 10230 {
errors.LogInfo(context.Background(), "allocate new ipv6 table index: ", tableIndex)
}
currentIndex := tableIndex
tableIndex++
return currentIndex
}
func newDeviceNet(interfaceName string) *deviceNet { func newDeviceNet(interfaceName string) *deviceNet {
var dialer net.Dialer var dialer net.Dialer
bindControl := control.BindToInterface(control.NewDefaultInterfaceFinder(), interfaceName, -1) bindControl := control.BindToInterface(control.NewDefaultInterfaceFinder(), interfaceName, -1)
@@ -68,7 +87,7 @@ func (d *deviceNet) Close() (err error) {
if len(errs) == 0 { if len(errs) == 0 {
return nil return nil
} }
return errors.Join(errs...) return goerrors.Join(errs...)
} }
func createKernelTun(localAddresses []netip.Addr, mtu int, handler promiscuousModeHandler) (t Tunnel, err error) { func createKernelTun(localAddresses []netip.Addr, mtu int, handler promiscuousModeHandler) (t Tunnel, err error) {
@@ -138,7 +157,7 @@ func createKernelTun(localAddresses []netip.Addr, mtu int, handler promiscuousMo
} }
} }
ipv6TableIndex := 1023 ipv6TableIndex := allocateIPv6TableIndex()
if v6 != nil { if v6 != nil {
r := &netlink.Route{Table: ipv6TableIndex} r := &netlink.Route{Table: ipv6TableIndex}
for { for {

View File

@@ -303,8 +303,8 @@ func TestCommanderAddRemoveUser(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -458,8 +458,8 @@ func TestCommanderStats(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -480,8 +480,8 @@ func TestCommanderStats(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },

View File

@@ -96,6 +96,7 @@ func InitializeServerConfig(config *core.Config) (*exec.Cmd, error) {
var ( var (
testBinaryPath string testBinaryPath string
testBinaryCleanFn func()
testBinaryPathGen sync.Once testBinaryPathGen sync.Once
) )
@@ -108,6 +109,7 @@ func genTestBinaryPath() {
return err return err
} }
tempDir = dir tempDir = dir
testBinaryCleanFn = func() { os.RemoveAll(dir) }
return nil return nil
})) }))
file := filepath.Join(tempDir, "xray.test") file := filepath.Join(tempDir, "xray.test")

View File

@@ -85,8 +85,8 @@ func TestDokodemoTCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -181,8 +181,8 @@ func TestDokodemoUDP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
}, },

View File

@@ -53,8 +53,8 @@ func TestPassiveConnection(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -161,8 +161,8 @@ func TestProxy(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -299,8 +299,8 @@ func TestProxyOverKCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -386,8 +386,8 @@ func TestBlackhole(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -397,8 +397,8 @@ func TestBlackhole(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest2.Address), Address: net.NewIPOrDomain(dest2.Address),
Port: uint32(dest2.Port), Port: uint32(dest2.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -512,8 +512,8 @@ func TestUDPConnection(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
}, },
@@ -556,8 +556,8 @@ func TestDomainSniffing(t *testing.T) {
}, },
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(net.LocalHostIP), Address: net.NewIPOrDomain(net.LocalHostIP),
Port: 443, Port: 443,
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },

View File

@@ -0,0 +1,12 @@
package scenarios
import (
"testing"
)
func TestMain(m *testing.M) {
genTestBinaryPath()
defer testBinaryCleanFn()
m.Run()
}

View File

@@ -110,8 +110,8 @@ func TestVMessClosing(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -214,8 +214,8 @@ func TestZeroBuffer(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },

View File

@@ -76,8 +76,8 @@ func TestReverseProxy(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -141,8 +141,8 @@ func TestReverseProxy(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -255,8 +255,8 @@ func TestReverseProxyLongRunning(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -334,8 +334,8 @@ func TestReverseProxyLongRunning(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },

View File

@@ -64,8 +64,8 @@ func TestSocksBridgeTCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -143,8 +143,8 @@ func TestSocksWithHttpRequest(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -213,8 +213,8 @@ func TestSocksBridageUDP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
}, },
@@ -247,8 +247,8 @@ func TestSocksBridageUDP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
}, },
@@ -328,8 +328,8 @@ func TestSocksBridageUDPWithRouting(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
}, },
@@ -366,8 +366,8 @@ func TestSocksBridageUDPWithRouting(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
}, },

View File

@@ -23,7 +23,6 @@ import (
"github.com/xtls/xray-core/testing/servers/udp" "github.com/xtls/xray-core/testing/servers/udp"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/grpc" "github.com/xtls/xray-core/transport/internet/grpc"
"github.com/xtls/xray-core/transport/internet/http"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/internet/websocket" "github.com/xtls/xray-core/transport/internet/websocket"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
@@ -81,8 +80,8 @@ func TestSimpleTLSConnection(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -196,8 +195,8 @@ func TestAutoIssuingCertificate(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -301,8 +300,8 @@ func TestTLSOverKCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -401,8 +400,8 @@ func TestTLSOverWebSocket(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -426,7 +425,7 @@ func TestTLSOverWebSocket(t *testing.T) {
}), }),
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
ProtocolName: "websocket", ProtocolName: "websocket",
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
{ {
ProtocolName: "websocket", ProtocolName: "websocket",
@@ -458,128 +457,6 @@ func TestTLSOverWebSocket(t *testing.T) {
} }
} }
func TestHTTP2(t *testing.T) {
tcpServer := tcp.Server{
MsgProcessor: xor,
}
dest, err := tcpServer.Start()
common.Must(err)
defer tcpServer.Close()
userID := protocol.NewID(uuid.New())
serverPort := tcp.PickPort()
serverConfig := &core.Config{
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP),
StreamSettings: &internet.StreamConfig{
ProtocolName: "http",
TransportSettings: []*internet.TransportConfig{
{
ProtocolName: "http",
Settings: serial.ToTypedMessage(&http.Config{
Host: []string{"example.com"},
Path: "/testpath",
}),
},
},
SecurityType: serial.GetMessageType(&tls.Config{}),
SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&tls.Config{
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
}),
},
},
}),
ProxySettings: serial.ToTypedMessage(&inbound.Config{
User: []*protocol.User{
{
Account: serial.ToTypedMessage(&vmess.Account{
Id: userID.String(),
}),
},
},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
clientPort := tcp.PickPort()
clientConfig := &core.Config{
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&outbound.Config{
Receiver: []*protocol.ServerEndpoint{
{
Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(serverPort),
User: []*protocol.User{
{
Account: serial.ToTypedMessage(&vmess.Account{
Id: userID.String(),
}),
},
},
},
},
}),
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
StreamSettings: &internet.StreamConfig{
ProtocolName: "http",
TransportSettings: []*internet.TransportConfig{
{
ProtocolName: "http",
Settings: serial.ToTypedMessage(&http.Config{
Host: []string{"example.com"},
Path: "/testpath",
}),
},
},
SecurityType: serial.GetMessageType(&tls.Config{}),
SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&tls.Config{
AllowInsecure: true,
}),
},
},
}),
},
},
}
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
common.Must(err)
defer CloseAllServers(servers)
var errg errgroup.Group
for i := 0; i < 10; i++ {
errg.Go(testTCPConn(clientPort, 1024*1024, time.Second*40))
}
if err := errg.Wait(); err != nil {
t.Error(err)
}
}
func TestGRPC(t *testing.T) { func TestGRPC(t *testing.T) {
tcpServer := tcp.Server{ tcpServer := tcp.Server{
MsgProcessor: xor, MsgProcessor: xor,
@@ -639,8 +516,8 @@ func TestGRPC(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -755,8 +632,8 @@ func TestGRPCMultiMode(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -866,8 +743,8 @@ func TestSimpleTLSConnectionPinned(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -968,8 +845,8 @@ func TestSimpleTLSConnectionPinnedWrongCert(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -1069,8 +946,8 @@ func TestUTLSConnectionPinned(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -1172,8 +1049,8 @@ func TestUTLSConnectionPinnedWrongCert(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },

View File

@@ -42,7 +42,7 @@ func TestHTTPConnectionHeader(t *testing.T) {
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
{ {
ProtocolName: "tcp", ProtocolName: "tcp",
Settings: serial.ToTypedMessage(&tcptransport.Config{ Settings: serial.ToTypedMessage(&tcptransport.Config{
HeaderSettings: serial.ToTypedMessage(&http.Config{}), HeaderSettings: serial.ToTypedMessage(&http.Config{}),
}), }),
}, },
@@ -76,8 +76,8 @@ func TestHTTPConnectionHeader(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -104,7 +104,7 @@ func TestHTTPConnectionHeader(t *testing.T) {
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
{ {
ProtocolName: "tcp", ProtocolName: "tcp",
Settings: serial.ToTypedMessage(&tcptransport.Config{ Settings: serial.ToTypedMessage(&tcptransport.Config{
HeaderSettings: serial.ToTypedMessage(&http.Config{}), HeaderSettings: serial.ToTypedMessage(&http.Config{}),
}), }),
}, },

View File

@@ -85,8 +85,8 @@ func TestVless(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -190,8 +190,8 @@ func TestVlessTls(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -215,7 +215,7 @@ func TestVlessTls(t *testing.T) {
}), }),
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
ProtocolName: "tcp", ProtocolName: "tcp",
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
{ {
ProtocolName: "tcp", ProtocolName: "tcp",
@@ -313,8 +313,8 @@ func TestVlessXtlsVision(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -339,7 +339,7 @@ func TestVlessXtlsVision(t *testing.T) {
}), }),
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
ProtocolName: "tcp", ProtocolName: "tcp",
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
{ {
ProtocolName: "tcp", ProtocolName: "tcp",
@@ -403,12 +403,12 @@ func TestVlessXtlsVisionReality(t *testing.T) {
SecurityType: serial.GetMessageType(&reality.Config{}), SecurityType: serial.GetMessageType(&reality.Config{}),
SecuritySettings: []*serial.TypedMessage{ SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&reality.Config{ serial.ToTypedMessage(&reality.Config{
Show: true, Show: true,
Dest: "www.google.com:443", // use google for now, may fail in some region Dest: "www.google.com:443", // use google for now, may fail in some region
ServerNames: []string{"www.google.com"}, ServerNames: []string{"www.google.com"},
PrivateKey: privateKey, PrivateKey: privateKey,
ShortIds: shortIds, ShortIds: shortIds,
Type: "tcp", Type: "tcp",
}), }),
}, },
}, },
@@ -447,8 +447,8 @@ func TestVlessXtlsVisionReality(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -473,7 +473,7 @@ func TestVlessXtlsVisionReality(t *testing.T) {
}), }),
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
ProtocolName: "tcp", ProtocolName: "tcp",
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
{ {
ProtocolName: "tcp", ProtocolName: "tcp",
@@ -483,12 +483,12 @@ func TestVlessXtlsVisionReality(t *testing.T) {
SecurityType: serial.GetMessageType(&reality.Config{}), SecurityType: serial.GetMessageType(&reality.Config{}),
SecuritySettings: []*serial.TypedMessage{ SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&reality.Config{ serial.ToTypedMessage(&reality.Config{
Show: true, Show: true,
Fingerprint: "chrome", Fingerprint: "chrome",
ServerName: "www.google.com", ServerName: "www.google.com",
PublicKey: publicKey, PublicKey: publicKey,
ShortId: shortIds[0], ShortId: shortIds[0],
SpiderX: "/", SpiderX: "/",
}), }),
}, },
}, },

View File

@@ -71,8 +71,8 @@ func TestVMessDynamicPort(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -131,8 +131,8 @@ func TestVMessDynamicPort(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -223,8 +223,8 @@ func TestVMessGCM(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -325,8 +325,8 @@ func TestVMessGCMReadv(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -430,8 +430,8 @@ func TestVMessGCMUDP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
}, },
@@ -529,8 +529,8 @@ func TestVMessChacha20(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -629,8 +629,8 @@ func TestVMessNone(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -731,8 +731,8 @@ func TestVMessKCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -802,11 +802,11 @@ func TestVMessKCPLarge(t *testing.T) {
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}}, PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
ProtocolName: "mkcp", ProtocolName: "mkcp",
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
{ {
ProtocolName: "mkcp", ProtocolName: "mkcp",
Settings: serial.ToTypedMessage(&kcp.Config{ Settings: serial.ToTypedMessage(&kcp.Config{
ReadBuffer: &kcp.ReadBuffer{ ReadBuffer: &kcp.ReadBuffer{
Size: 512 * 1024, Size: 512 * 1024,
}, },
@@ -857,8 +857,8 @@ func TestVMessKCPLarge(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -885,11 +885,11 @@ func TestVMessKCPLarge(t *testing.T) {
}), }),
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
StreamSettings: &internet.StreamConfig{ StreamSettings: &internet.StreamConfig{
ProtocolName: "mkcp", ProtocolName: "mkcp",
TransportSettings: []*internet.TransportConfig{ TransportSettings: []*internet.TransportConfig{
{ {
ProtocolName: "mkcp", ProtocolName: "mkcp",
Settings: serial.ToTypedMessage(&kcp.Config{ Settings: serial.ToTypedMessage(&kcp.Config{
ReadBuffer: &kcp.ReadBuffer{ ReadBuffer: &kcp.ReadBuffer{
Size: 512 * 1024, Size: 512 * 1024,
}, },
@@ -984,8 +984,8 @@ func TestVMessGCMMux(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -1100,8 +1100,8 @@ func TestVMessGCMMuxUDP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -1111,8 +1111,8 @@ func TestVMessGCMMuxUDP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(udpDest.Address), Address: net.NewIPOrDomain(udpDest.Address),
Port: uint32(udpDest.Port), Port: uint32(udpDest.Port),
Networks: []net.Network{net.Network_UDP}, Networks: []net.Network{net.Network_UDP},
}), }),
}, },
@@ -1224,8 +1224,8 @@ func TestVMessZero(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -1323,8 +1323,8 @@ func TestVMessGCMLengthAuth(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },
@@ -1427,8 +1427,8 @@ func TestVMessGCMLengthAuthPlusNoTerminationSignal(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
Networks: []net.Network{net.Network_TCP}, Networks: []net.Network{net.Network_TCP},
}), }),
}, },

View File

@@ -152,9 +152,9 @@ type TransportConfig struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Type of network that this settings supports. // Transport protocol name.
ProtocolName string `protobuf:"bytes,3,opt,name=protocol_name,json=protocolName,proto3" json:"protocol_name,omitempty"` ProtocolName string `protobuf:"bytes,3,opt,name=protocol_name,json=protocolName,proto3" json:"protocol_name,omitempty"`
// Specific settings. Must be of the transports. // Specific transport protocol settings.
Settings *serial.TypedMessage `protobuf:"bytes,2,opt,name=settings,proto3" json:"settings,omitempty"` Settings *serial.TypedMessage `protobuf:"bytes,2,opt,name=settings,proto3" json:"settings,omitempty"`
} }
@@ -214,7 +214,7 @@ type StreamConfig struct {
TransportSettings []*TransportConfig `protobuf:"bytes,2,rep,name=transport_settings,json=transportSettings,proto3" json:"transport_settings,omitempty"` TransportSettings []*TransportConfig `protobuf:"bytes,2,rep,name=transport_settings,json=transportSettings,proto3" json:"transport_settings,omitempty"`
// Type of security. Must be a message name of the settings proto. // Type of security. Must be a message name of the settings proto.
SecurityType string `protobuf:"bytes,3,opt,name=security_type,json=securityType,proto3" json:"security_type,omitempty"` SecurityType string `protobuf:"bytes,3,opt,name=security_type,json=securityType,proto3" json:"security_type,omitempty"`
// Settings for transport security. For now the only choice is TLS. // Transport security settings. They can be either TLS or REALITY.
SecuritySettings []*serial.TypedMessage `protobuf:"bytes,4,rep,name=security_settings,json=securitySettings,proto3" json:"security_settings,omitempty"` SecuritySettings []*serial.TypedMessage `protobuf:"bytes,4,rep,name=security_settings,json=securitySettings,proto3" json:"security_settings,omitempty"`
SocketSettings *SocketConfig `protobuf:"bytes,6,opt,name=socket_settings,json=socketSettings,proto3" json:"socket_settings,omitempty"` SocketSettings *SocketConfig `protobuf:"bytes,6,opt,name=socket_settings,json=socketSettings,proto3" json:"socket_settings,omitempty"`
} }
@@ -448,7 +448,7 @@ type SocketConfig struct {
TcpWindowClamp int32 `protobuf:"varint,15,opt,name=tcp_window_clamp,json=tcpWindowClamp,proto3" json:"tcp_window_clamp,omitempty"` TcpWindowClamp int32 `protobuf:"varint,15,opt,name=tcp_window_clamp,json=tcpWindowClamp,proto3" json:"tcp_window_clamp,omitempty"`
TcpUserTimeout int32 `protobuf:"varint,16,opt,name=tcp_user_timeout,json=tcpUserTimeout,proto3" json:"tcp_user_timeout,omitempty"` TcpUserTimeout int32 `protobuf:"varint,16,opt,name=tcp_user_timeout,json=tcpUserTimeout,proto3" json:"tcp_user_timeout,omitempty"`
TcpMaxSeg int32 `protobuf:"varint,17,opt,name=tcp_max_seg,json=tcpMaxSeg,proto3" json:"tcp_max_seg,omitempty"` TcpMaxSeg int32 `protobuf:"varint,17,opt,name=tcp_max_seg,json=tcpMaxSeg,proto3" json:"tcp_max_seg,omitempty"`
TcpNoDelay bool `protobuf:"varint,18,opt,name=tcp_no_delay,json=tcpNoDelay,proto3" json:"tcp_no_delay,omitempty"` Penetrate bool `protobuf:"varint,18,opt,name=penetrate,proto3" json:"penetrate,omitempty"`
TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"` TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"`
CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"` CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"`
} }
@@ -602,9 +602,9 @@ func (x *SocketConfig) GetTcpMaxSeg() int32 {
return 0 return 0
} }
func (x *SocketConfig) GetTcpNoDelay() bool { func (x *SocketConfig) GetPenetrate() bool {
if x != nil { if x != nil {
return x.TcpNoDelay return x.Penetrate
} }
return false return false
} }
@@ -678,7 +678,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{
0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a,
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
0x65, 0x22, 0x9f, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x65, 0x22, 0x9b, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20,
0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f,
@@ -724,36 +724,36 @@ var file_transport_internet_config_proto_rawDesc = []byte{
0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x63, 0x70, 0x55, 0x73, 0x65, 0x72, 0x54, 0x69, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x63, 0x70, 0x55, 0x73, 0x65, 0x72, 0x54, 0x69,
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x61, 0x78, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x61, 0x78,
0x5f, 0x73, 0x65, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x63, 0x70, 0x4d, 0x5f, 0x73, 0x65, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x63, 0x70, 0x4d,
0x61, 0x78, 0x53, 0x65, 0x67, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x63, 0x70, 0x5f, 0x6e, 0x6f, 0x5f, 0x61, 0x78, 0x53, 0x65, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x6e, 0x65, 0x74, 0x72, 0x61,
0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x74, 0x63, 0x70, 0x74, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x6e, 0x65, 0x74, 0x72,
0x4e, 0x6f, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x70, 0x74, 0x63, 0x70,
0x70, 0x74, 0x63, 0x70, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x63, 0x70, 0x4d, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x63, 0x70, 0x4d, 0x70, 0x74, 0x63, 0x70,
0x70, 0x74, 0x63, 0x70, 0x12, 0x4c, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x12, 0x4c, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70,
0x63, 0x6b, 0x6f, 0x70, 0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x52,
0x6f, 0x70, 0x74, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x22, 0x2f,
0x70, 0x74, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03,
0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10,
0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a,
0x74, 0x10, 0x02, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a,
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45,
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10,
0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12,
0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a,
0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09,
0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46,
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46,
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42, 0x67, 0x0a, 0x1b, 0x63,
0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69,
0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72,
0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61,
0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65,
0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@@ -24,10 +24,10 @@ enum DomainStrategy {
} }
message TransportConfig { message TransportConfig {
// Type of network that this settings supports. // Transport protocol name.
string protocol_name = 3; string protocol_name = 3;
// Specific settings. Must be of the transports. // Specific transport protocol settings.
xray.common.serial.TypedMessage settings = 2; xray.common.serial.TypedMessage settings = 2;
} }
@@ -43,7 +43,7 @@ message StreamConfig {
// Type of security. Must be a message name of the settings proto. // Type of security. Must be a message name of the settings proto.
string security_type = 3; string security_type = 3;
// Settings for transport security. For now the only choice is TLS. // Transport security settings. They can be either TLS or REALITY.
repeated xray.common.serial.TypedMessage security_settings = 4; repeated xray.common.serial.TypedMessage security_settings = 4;
SocketConfig socket_settings = 6; SocketConfig socket_settings = 6;
@@ -103,7 +103,7 @@ message SocketConfig {
string interface = 13; string interface = 13;
bool v6only = 14; bool v6only = 14;
int32 tcp_window_clamp = 15; int32 tcp_window_clamp = 15;
@@ -111,7 +111,7 @@ message SocketConfig {
int32 tcp_max_seg = 17; int32 tcp_max_seg = 17;
bool tcp_no_delay = 18; bool penetrate = 18;
bool tcp_mptcp = 19; bool tcp_mptcp = 19;

View File

@@ -56,7 +56,7 @@ func dialgRPC(ctx context.Context, dest net.Destination, streamSettings *interne
} }
client := encoding.NewGRPCServiceClient(conn) client := encoding.NewGRPCServiceClient(conn)
if grpcSettings.MultiMode { if grpcSettings.MultiMode {
errors.LogDebug(ctx, "using gRPC multi mode service name: `" + grpcSettings.getServiceName() + "` stream name: `" + grpcSettings.getTunMultiStreamName() + "`") errors.LogDebug(ctx, "using gRPC multi mode service name: `"+grpcSettings.getServiceName()+"` stream name: `"+grpcSettings.getTunMultiStreamName()+"`")
grpcService, err := client.(encoding.GRPCServiceClientX).TunMultiCustomName(ctx, grpcSettings.getServiceName(), grpcSettings.getTunMultiStreamName()) grpcService, err := client.(encoding.GRPCServiceClientX).TunMultiCustomName(ctx, grpcSettings.getServiceName(), grpcSettings.getTunMultiStreamName())
if err != nil { if err != nil {
return nil, errors.New("Cannot dial gRPC").Base(err) return nil, errors.New("Cannot dial gRPC").Base(err)
@@ -64,7 +64,7 @@ func dialgRPC(ctx context.Context, dest net.Destination, streamSettings *interne
return encoding.NewMultiHunkConn(grpcService, nil), nil return encoding.NewMultiHunkConn(grpcService, nil), nil
} }
errors.LogDebug(ctx, "using gRPC tun mode service name: `" + grpcSettings.getServiceName() + "` stream name: `" + grpcSettings.getTunStreamName() + "`") errors.LogDebug(ctx, "using gRPC tun mode service name: `"+grpcSettings.getServiceName()+"` stream name: `"+grpcSettings.getTunStreamName()+"`")
grpcService, err := client.(encoding.GRPCServiceClientX).TunCustomName(ctx, grpcSettings.getServiceName(), grpcSettings.getTunStreamName()) grpcService, err := client.(encoding.GRPCServiceClientX).TunCustomName(ctx, grpcSettings.getServiceName(), grpcSettings.getTunStreamName())
if err != nil { if err != nil {
return nil, errors.New("Cannot dial gRPC").Base(err) return nil, errors.New("Cannot dial gRPC").Base(err)

View File

@@ -120,7 +120,7 @@ func Listen(ctx context.Context, address net.Address, port net.Port, settings *i
} }
} }
errors.LogDebug(ctx, "gRPC listen for service name `" + grpcSettings.getServiceName() + "` tun `" + grpcSettings.getTunStreamName() + "` multi tun `" + grpcSettings.getTunMultiStreamName() + "`") errors.LogDebug(ctx, "gRPC listen for service name `"+grpcSettings.getServiceName()+"` tun `"+grpcSettings.getTunStreamName()+"` multi tun `"+grpcSettings.getTunMultiStreamName()+"`")
encoding.RegisterGRPCServiceServerX(s, listener, grpcSettings.getServiceName(), grpcSettings.getTunStreamName(), grpcSettings.getTunMultiStreamName()) encoding.RegisterGRPCServiceServerX(s, listener, grpcSettings.getServiceName(), grpcSettings.getTunStreamName(), grpcSettings.getTunMultiStreamName())
if config := reality.ConfigFromStreamSettings(settings); config != nil { if config := reality.ConfigFromStreamSettings(settings); config != nil {

View File

@@ -1,48 +0,0 @@
package http
import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/transport/internet"
)
func (c *Config) getHosts() []string {
if len(c.Host) == 0 {
return []string{"www.example.com"}
}
return c.Host
}
func (c *Config) isValidHost(host string) bool {
if len(c.Host) == 0 {
return true
}
hosts := c.getHosts()
for _, h := range hosts {
if internet.IsValidHTTPHost(host, h) {
return true
}
}
return false
}
func (c *Config) getRandomHost() string {
hosts := c.getHosts()
return hosts[dice.Roll(len(hosts))]
}
func (c *Config) getNormalizedPath() string {
if c.Path == "" {
return "/"
}
if c.Path[0] != '/' {
return "/" + c.Path
}
return c.Path
}
func init() {
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
return new(Config)
}))
}

View File

@@ -1,193 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.1
// protoc v5.28.2
// source: transport/internet/http/config.proto
package http
import (
http "github.com/xtls/xray-core/transport/internet/headers/http"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Host []string `protobuf:"bytes,1,rep,name=host,proto3" json:"host,omitempty"`
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
IdleTimeout int32 `protobuf:"varint,3,opt,name=idle_timeout,json=idleTimeout,proto3" json:"idle_timeout,omitempty"`
HealthCheckTimeout int32 `protobuf:"varint,4,opt,name=health_check_timeout,json=healthCheckTimeout,proto3" json:"health_check_timeout,omitempty"`
Method string `protobuf:"bytes,5,opt,name=method,proto3" json:"method,omitempty"`
Header []*http.Header `protobuf:"bytes,6,rep,name=header,proto3" json:"header,omitempty"`
}
func (x *Config) Reset() {
*x = Config{}
mi := &file_transport_internet_http_config_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Config) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_transport_internet_http_config_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_transport_internet_http_config_proto_rawDescGZIP(), []int{0}
}
func (x *Config) GetHost() []string {
if x != nil {
return x.Host
}
return nil
}
func (x *Config) GetPath() string {
if x != nil {
return x.Path
}
return ""
}
func (x *Config) GetIdleTimeout() int32 {
if x != nil {
return x.IdleTimeout
}
return 0
}
func (x *Config) GetHealthCheckTimeout() int32 {
if x != nil {
return x.HealthCheckTimeout
}
return 0
}
func (x *Config) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}
func (x *Config) GetHeader() []*http.Header {
if x != nil {
return x.Header
}
return nil
}
var File_transport_internet_http_config_proto protoreflect.FileDescriptor
var file_transport_internet_http_config_proto_rawDesc = []byte{
0x0a, 0x24, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
0x68, 0x74, 0x74, 0x70, 0x1a, 0x2c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
0x2f, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0xe3, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a,
0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73,
0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x69,
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x69, 0x64, 0x6c,
0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x65, 0x61, 0x6c,
0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68,
0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68,
0x6f, 0x64, 0x12, 0x44, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x65, 0x72, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x76, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x50, 0x01, 0x5a, 0x31,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x74, 0x74,
0x70, 0xaa, 0x02, 0x1c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x48, 0x74, 0x74, 0x70,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_transport_internet_http_config_proto_rawDescOnce sync.Once
file_transport_internet_http_config_proto_rawDescData = file_transport_internet_http_config_proto_rawDesc
)
func file_transport_internet_http_config_proto_rawDescGZIP() []byte {
file_transport_internet_http_config_proto_rawDescOnce.Do(func() {
file_transport_internet_http_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_http_config_proto_rawDescData)
})
return file_transport_internet_http_config_proto_rawDescData
}
var file_transport_internet_http_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_transport_internet_http_config_proto_goTypes = []any{
(*Config)(nil), // 0: xray.transport.internet.http.Config
(*http.Header)(nil), // 1: xray.transport.internet.headers.http.Header
}
var file_transport_internet_http_config_proto_depIdxs = []int32{
1, // 0: xray.transport.internet.http.Config.header:type_name -> xray.transport.internet.headers.http.Header
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_transport_internet_http_config_proto_init() }
func file_transport_internet_http_config_proto_init() {
if File_transport_internet_http_config_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_transport_internet_http_config_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_transport_internet_http_config_proto_goTypes,
DependencyIndexes: file_transport_internet_http_config_proto_depIdxs,
MessageInfos: file_transport_internet_http_config_proto_msgTypes,
}.Build()
File_transport_internet_http_config_proto = out.File
file_transport_internet_http_config_proto_rawDesc = nil
file_transport_internet_http_config_proto_goTypes = nil
file_transport_internet_http_config_proto_depIdxs = nil
}

View File

@@ -1,18 +0,0 @@
syntax = "proto3";
package xray.transport.internet.http;
option csharp_namespace = "Xray.Transport.Internet.Http";
option go_package = "github.com/xtls/xray-core/transport/internet/http";
option java_package = "com.xray.transport.internet.http";
option java_multiple_files = true;
import "transport/internet/headers/http/config.proto";
message Config {
repeated string host = 1;
string path = 2;
int32 idle_timeout = 3;
int32 health_check_timeout = 4;
string method = 5;
repeated xray.transport.internet.headers.http.Header header = 6;
}

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