Compare commits

...

82 Commits

Author SHA1 Message Date
yuhan6665
1c8375997d Update 1.8.8 and dependencies 2024-02-25 09:31:59 -05:00
yuhan6665
57f0a6712f Revert "Fix a little version issue"
This reverts commit c100d35b88.
2024-02-21 17:40:27 -05:00
dependabot[bot]
d5e94deea6 Bump github.com/sagernet/sing from 0.3.0 to 0.3.2
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.3.0 to 0.3.2.
- [Commits](https://github.com/sagernet/sing/compare/v0.3.0...v0.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 12:15:08 -05:00
dependabot[bot]
84d9c63bdb Bump google.golang.org/grpc from 1.61.1 to 1.62.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.61.1 to 1.62.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.61.1...v1.62.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 12:12:18 -05:00
dependabot[bot]
51bacf7722 Bump github.com/refraction-networking/utls from 1.6.2 to 1.6.3
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.6.2 to 1.6.3.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.6.2...v1.6.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 12:12:10 -05:00
yuhan6665
3778a367c8 Fix and simplify SockOpt in UDP
https://github.com/golang/go/issues/29277
2024-02-21 13:59:09 -05:00
yuhan6665
a0f1e1f377 FakeDNS return TTL=1 and drop HTTPS QType 65 request
Co-authored-by: qwerr0
2024-02-21 11:09:51 -05:00
风扇滑翔翼
c100d35b88 Fix a little version issue 2024-02-21 10:57:51 -05:00
Allo
f9653d0d88 chore(ci): use go version file to specify the go version 2024-02-20 10:45:25 -05:00
RPRX
ad3dd3df56 Update go.mod to specify Go 1.22 2024-02-19 15:16:43 +00:00
deorth-kku
cae94570df Fixing tcp connestions leak
- always use HandshakeContext instead of Handshake

- pickup dailer dropped ctx

- rename HandshakeContextAddress to HandshakeAddressContext
2024-02-19 09:32:40 -05:00
RPRX
5ea1315b85 Update workflows to use Go 1.22 2024-02-18 06:55:47 +00:00
yuhan6665
fa5d7a255b Least load balancer (#2999)
* v5: Health Check & LeastLoad Strategy (rebased from 2c5a71490368500a982018a74a6d519c7e121816)

Some changes will be necessary to integrate it into V2Ray

* Update proto

* parse duration conf with time.Parse()

* moving health ping to observatory as a standalone component

* moving health ping to observatory as a standalone component: auto generated file

* add initialization for health ping

* incorporate changes in router implementation

* support principle target output

* add v4 json support for BurstObservatory & fix balancer reference

* update API command

* remove cancelled API

* return zero length value when observer is not found

* remove duplicated targeted dispatch

* adjust test with updated structure

* bug fix for observer

* fix strategy selector

* fix strategy least load

* Fix ticker usage

ticker.Close does not close ticker.C

* feat: Replace default Health Ping URL to HTTPS (#1991)

* fix selectLeastLoad() returns wrong number of nodes (#2083)

* Test: fix leastload strategy unit test

* fix(router): panic caused by concurrent map read and write (#2678)

* Clean up code

---------

Co-authored-by: Jebbs <qjebbs@gmail.com>
Co-authored-by: Shelikhoo <xiaokangwang@outlook.com>
Co-authored-by: 世界 <i@sekai.icu>
Co-authored-by: Bernd Eichelberger <46166740+4-FLOSS-Free-Libre-Open-Source-Software@users.noreply.github.com>
Co-authored-by: 秋のかえで <autmaple@protonmail.com>
Co-authored-by: Rinka <kujourinka@gmail.com>
2024-02-17 22:51:37 -05:00
yuhan6665
bf02392969 Temporarily turn off sockopt for UDP on windows 2024-02-17 13:22:39 -05:00
yuhan6665
a15334b395 Go back to first fix (revet d21e9b0abd)
Xtls is magic, don't play with it ;)

A knowledged guess is the timing to switch to splice is very sensitive. Now both Xtls and Freedom outound do the switching when pipe just finished one buffer
2024-02-17 11:16:37 -05:00
yuhan6665
09656bd5d1 Add back sleep for freedom splice 2024-02-15 21:18:56 -05:00
dependabot[bot]
40e41d8b6b Bump google.golang.org/grpc from 1.61.0 to 1.61.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.61.0 to 1.61.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.61.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-15 10:28:14 -05:00
lunafe
b091076bae fix #2970 parsing IPv6 address in wireguard peers configure 2024-02-12 10:45:12 -05:00
dependabot[bot]
7c9e3f97f1 Bump golang.org/x/net from 0.20.0 to 0.21.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.20.0 to 0.21.0.
- [Commits](https://github.com/golang/net/compare/v0.20.0...v0.21.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-07 21:08:24 -05:00
dependabot[bot]
c5713eb952 Bump golang.org/x/crypto from 0.18.0 to 0.19.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.18.0 to 0.19.0.
- [Commits](https://github.com/golang/crypto/compare/v0.18.0...v0.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-07 21:06:23 -05:00
dependabot[bot]
7c8bec8596 Bump golang.org/x/sys from 0.16.0 to 0.17.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/sys/compare/v0.16.0...v0.17.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-07 21:06:16 -05:00
yuhan6665
d83ccaeea9 Clean up legacy compile directive 2024-02-06 21:17:21 -05:00
风扇滑翔翼
303beff5dd Fix SockOpt does not work in UDP 2024-02-06 10:41:39 -05:00
Iain Lau
3a99520370 Add PROXY Protocol support for freedom outbound 2024-02-05 10:08:51 -05:00
RPRX
b56917fde5 README: Re-add Compilation 2024-02-04 09:36:41 +00:00
RPRX
ad3d347cfc XTLS Vision: Apply padding to single XUDP by default at client side
Requires Xray-core v1.8.1+ at server side: 242f3b0e0b
2024-02-02 20:32:46 +00:00
dependabot[bot]
dd635c7c8d Bump nick-fields/retry from 2 to 3
Bumps [nick-fields/retry](https://github.com/nick-fields/retry) from 2 to 3.
- [Release notes](https://github.com/nick-fields/retry/releases)
- [Changelog](https://github.com/nick-fields/retry/blob/master/.releaserc.js)
- [Commits](https://github.com/nick-fields/retry/compare/v2...v3)

---
updated-dependencies:
- dependency-name: nick-fields/retry
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-31 22:58:46 -05:00
dependabot[bot]
813f9a33b7 Bump github.com/refraction-networking/utls from 1.6.1 to 1.6.2
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.6.1 to 1.6.2.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.6.1...v1.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-30 10:38:49 -05:00
yuhan6665
d21e9b0abd Try a better fix for rare ssl error with freedom splice
It seems the root cause is if the flag set at the inbound pipe reader, it is a race condition and freedom outbound can possibly do splice at the same time with inbound xtls writer.
Now we set the flag at the earliest and always do splice at the next buffer cycle.
2024-01-26 04:42:45 -05:00
yuhan6665
3167a70ff8 Try to fix rare ssl error with freedom splice 2024-01-26 02:29:26 -05:00
チセ
25c531c6c3 Update README.md 2024-01-25 10:10:13 -05:00
dependabot[bot]
d97a29f55b Bump google.golang.org/grpc from 1.60.1 to 1.61.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.60.1 to 1.61.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.60.1...v1.61.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-24 10:25:16 -05:00
dependabot[bot]
53de58fad3 Bump github.com/miekg/dns from 1.1.57 to 1.1.58
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.57 to 1.1.58.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.57...v1.1.58)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-20 16:40:34 -05:00
dependabot[bot]
4bffd5114d Bump github.com/quic-go/quic-go from 0.40.1 to 0.41.0
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.40.1 to 0.41.0.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.40.1...v0.41.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-20 16:40:22 -05:00
dependabot[bot]
360272a77d Bump actions/cache from 3 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-20 16:40:09 -05:00
nobody
d20a835016 Fix concurrent map writes error in ohm.Select(). (#2943)
* Add unit test for ohm.tagsCache.

* Fix concurrent map writes in ohm.Select().

---------

Co-authored-by: nobody <nobody@nowhere.mars>
2024-01-16 10:52:01 -05:00
yuhan6665
10255bca83 Reduce size and time of KCP test 2024-01-15 10:37:56 -05:00
dyhkwong
da5a28a088 Fix #2654 (#2941)
* fix udp dispatcher

* fix test
2024-01-15 10:33:15 -05:00
yuhan6665
77376ed94f Reduce size and time of UDP test
In the past, the UDP test in mass parallel proved to be the source of instability. This change try to improve pass rate.
2024-01-12 22:09:04 -05:00
nobody
7f7f57d3b6 Add tags cache to app.proxyman.ohm.Select() (#2927)
* Add tags cache to ohm.Select().

* Refactor round-robin.

* Fix a bug.

---------

Co-authored-by: nobody <nobody@nowhere.mars>
2024-01-12 10:36:48 -05:00
Qi Lin
0ea2a50264 Add option realitySettings.masterKeyLog 2024-01-11 10:57:04 -05:00
nobody
961cf9d3b1 Remove slices dependency. (#2930)
* Remove slices dependency.

* Fix nil pointer dereference bug.

---------

Co-authored-by: nobody <nobody@nowhere.mars>
2024-01-11 10:34:26 -05:00
Qi Lin
2b08d8638e Let tlsSettings.masterKeyLog and tlsSettings.fingerprint work together 2024-01-10 11:34:52 -05:00
Hossin Asaadi
81f9f567ff sort Outbound selector output (#2914)
* clean code

* sort oubound selector output

* clean up

* fix duplicate outbound
2024-01-10 11:26:27 -05:00
dependabot[bot]
2fa5c299ac Bump github.com/refraction-networking/utls from 1.6.0 to 1.6.1
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.6.0...v1.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-10 11:18:40 -05:00
dependabot[bot]
8a6b9e7420 Bump golang.org/x/net from 0.19.0 to 0.20.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.19.0 to 0.20.0.
- [Commits](https://github.com/golang/net/compare/v0.19.0...v0.20.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-10 11:18:31 -05:00
yuhan6665
3f0bc13429 Update 1.8.7 and dependencies 2024-01-07 15:19:18 -05:00
hossinasaadi
9a2ab9b6a3 fix roundRobin 2024-01-07 14:27:37 -05:00
Lars Lehtonen
2fc4b31fcf common/singbridge: fix dropped context 2024-01-02 19:56:14 -05:00
チセ
7b4db50c9d Feat: Using Makefile to build xray (#2882)
* Feat: Using `Makefile` to build xray

* Typo
2024-01-02 10:13:38 -05:00
dop-bot
60f7a03e1b fix(dns): avoid early return when dns query refused (#2878)
* avoid early return when dns query refused

* address reviews
2024-01-01 23:03:36 -05:00
nobody
44bb83033f Add sub-command "-dump" to "run". (#2854)
* Add MarshalToJson().

* Add cmd arg -dump for printing out merged multiple json configs.

---------

Co-authored-by: nobody <nobody@nowhere.mars>
2023-12-29 11:16:48 -05:00
Allo
006cf491e5 fix(conf): add Windows support for Unix Domain Socket in the fallback settings 2023-12-29 11:07:41 -05:00
R8s6
1dba70004f Update README.md
Adding official docker repo.
2023-12-29 10:58:15 -05:00
dependabot[bot]
1dc9a72068 Bump google.golang.org/protobuf from 1.31.0 to 1.32.0
Bumps google.golang.org/protobuf from 1.31.0 to 1.32.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>
2023-12-25 22:25:43 -05:00
yuhan6665
eacdda3c93 Fix connecting to quic outbound with domain address 2023-12-25 22:25:22 -05:00
Allo
b0bf0d7fd5 fix(conf): add Windows support for Unix Domain Socket 2023-12-24 15:48:25 -05:00
hossinasaadi
b7f21be8bc fix ecdh crash in reality 2023-12-24 15:38:44 -05:00
Hossin Asaadi
01c14a5994 add Round-Robin Strategy to balancer (#2844)
* add Round-Robin Strategy

* clean up
2023-12-24 15:29:10 -05:00
风扇滑翔翼
9becf02316 allow empty route type
default field
2023-12-24 15:00:23 -05:00
dependabot[bot]
f51bf98714 Bump golang.org/x/crypto from 0.16.0 to 0.17.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.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>
2023-12-20 10:18:55 -05:00
dependabot[bot]
5e19c1a778 Bump google.golang.org/grpc from 1.60.0 to 1.60.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.60.0 to 1.60.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.60.0...v1.60.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-20 10:18:45 -05:00
dependabot[bot]
e03b78dcec Bump github.com/refraction-networking/utls from 1.5.4 to 1.6.0
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.5.4 to 1.6.0.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.5.4...v1.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 18:37:08 -05:00
yuhan6665
d60281d0a5 Add DestIpAddress() in Dialer interface
Android client prepares an IP before proxy connection is established. It is useful when connecting to wireguard (or quic) outbound with domain address. E.g. engage.cloudflareclient.com:2408
2023-12-18 18:36:56 -05:00
Zhang San
5a5e615b46 Enable interface setting for socketopt under Windows (#2819)
* allow set interface under windows

Signed-off-by: San Zhang <zhangan@mail.com>

* polish code

Signed-off-by: San Zhang <zhangan@mail.com>

---------

Signed-off-by: San Zhang <zhangan@mail.com>
Co-authored-by: San Zhang <zhangan@mail.com>
2023-12-17 17:56:15 -05:00
H1JK
c01a30e8f4 Cleanup sing buffer usage 2023-12-17 17:37:08 -05:00
dependabot[bot]
38b175d53e Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 09:53:23 -05:00
dependabot[bot]
53ac4c031d Bump github.com/quic-go/quic-go from 0.40.0 to 0.40.1
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.40.0 to 0.40.1.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.40.0...v0.40.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-14 10:58:46 -05:00
wyx2685
31a8fae764 Fix deprecated StackNew() function 2023-12-12 11:28:26 -05:00
dependabot[bot]
46d6b9f57a Bump github.com/sagernet/sing from 0.2.18 to 0.2.19
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.18 to 0.2.19.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.18...v0.2.19)

---
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>
2023-12-11 20:52:54 -05:00
dependabot[bot]
921be3ac40 Bump google.golang.org/grpc from 1.59.0 to 1.60.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.59.0 to 1.60.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.59.0...v1.60.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 20:52:42 -05:00
チセ
2da476eef4 Command: Add wg for wireguard key generation (#2794)
* Command: Add `wg` for wireguard key generation

* Command: Merge `x25519` and `wg`
2023-12-11 20:52:10 -05:00
Yu FranzKafka
2c97beae4e delete my repo for unnecessary disputes
写了半天英文,感觉挺别扭的,还是用中文吧。

因为闭源的缘故,很抱歉给社区带来了负面影响;同时也是由于生活所迫,自己再没有额外的精力维护项目。自此,我提议在README中删除我的项目,并推荐大家使用其他仍在维护的版本。  

原本想说的话有很多,千言万语到此都作烟消云散。  

相信我不会离开,我们总会以其他的方式再次见面。
2023-12-11 15:07:35 -05:00
dependabot[bot]
4e7a57ef86 Bump github.com/sagernet/sing-shadowsocks from 0.2.5 to 0.2.6
Bumps [github.com/sagernet/sing-shadowsocks](https://github.com/sagernet/sing-shadowsocks) from 0.2.5 to 0.2.6.
- [Commits](https://github.com/sagernet/sing-shadowsocks/compare/v0.2.5...v0.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-10 22:49:35 -05:00
Lars Lehtonen
06734d6f08 common/ocsp: fix dropped error 2023-12-09 19:52:50 -05:00
dependabot[bot]
1444552691 Bump actions/setup-go from 4 to 5
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-07 10:15:57 -05:00
dependabot[bot]
0c3e1d4bd9 Bump github.com/sagernet/sing from 0.2.17 to 0.2.18
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.17 to 0.2.18.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.17...v0.2.18)

---
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>
2023-12-05 10:22:51 -05:00
Gorilla
c590163f9f Update README.md
Add link to tutorial for "Xray with WireGuard inbound"
2023-12-04 10:20:19 -05:00
yuhan6665
2fd765ea4c Delay XUDP Basekey read 2023-12-03 22:10:10 -05:00
dependabot[bot]
be21b1194b Bump golang.org/x/net from 0.18.0 to 0.19.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.18.0 to 0.19.0.
- [Commits](https://github.com/golang/net/compare/v0.18.0...v0.19.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>
2023-11-28 11:30:07 -05:00
风扇滑翔翼
69cbb4c47a Change WS upgraderBufferSize
due to https://github.com/gorilla/websocket/issues/223
2023-11-28 11:28:58 -05:00
yuhan6665
6f092bd212 Add "masterKeyLog" in TLS config (#2758)
* Add "enableMasterKeyLog" in TLS config

Turn on the debug option for Wireshark to decrypt traffic

* Change to "masterKeyLog" to configure a path
2023-11-27 10:08:34 -05:00
171 changed files with 4843 additions and 802 deletions

View File

@@ -24,14 +24,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Restore Cache
uses: actions/cache/restore@v3
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Update Geodat
id: update
uses: nick-fields/retry@v2
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
retry_wait_seconds: 60
@@ -57,7 +57,7 @@ jobs:
done
- name: Save Cache
uses: actions/cache/save@v3
uses: actions/cache/save@v4
if: ${{ steps.update.outputs.unhit }}
with:
path: resources
@@ -165,47 +165,22 @@ jobs:
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version-file: go.mod
check-latest: true
- name: Get project dependencies
run: go mod download
- name: Replace Custom to Commit ID
if: github.event_name != 'release'
run: |
ID=$(git rev-parse --short ${{ github.sha }})
if [ "${{ github.event_name }}" == 'pull_request' ]
then
ID=$(git rev-parse --short ${{ github.event.pull_request.head.sha }})
fi
sed -i '/build/ s/Custom/'$ID'/' ./core/core.go
- name: Build Xray
run: |
mkdir -p build_assets
go build -v -o build_assets/xray -trimpath -ldflags "-s -w -buildid=" ./main
- name: Build background Xray on Windows
if: matrix.goos == 'windows'
run: |
go build -v -o build_assets/wxray.exe -trimpath -ldflags "-s -w -H windowsgui -buildid=" ./main
- name: Build Mips softfloat Xray
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
run: |
GOMIPS=softfloat go build -v -o build_assets/xray_softfloat -trimpath -ldflags "-s -w -buildid=" ./main
- name: Rename Windows Xray
if: matrix.goos == 'windows'
run: |
cd ./build_assets || exit 1
mv xray xray.exe
make
find . -maxdepth 1 -type f -regex '.*\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \;
- name: Restore Cache
uses: actions/cache/restore@v3
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
@@ -235,7 +210,7 @@ jobs:
mv build_assets Xray-${{ env.ASSET_NAME }}
- name: Upload files to Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Xray-${{ env.ASSET_NAME }}
path: |

View File

@@ -27,15 +27,15 @@ jobs:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
check-latest: true
- name: Checkout codebase
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
check-latest: true
- name: Restore Cache
uses: actions/cache/restore@v3
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-

2
.gitignore vendored
View File

@@ -19,6 +19,7 @@
*.zip
*.tar.gz
xray
xray_softfloat
mockgen
vprotogen
!infra/vprotogen/
@@ -26,3 +27,4 @@ errorgen
!common/errors/errorgen/
*.dat
.vscode
/build_assets

29
Makefile Normal file
View File

@@ -0,0 +1,29 @@
NAME = xray
VERSION=$(shell git describe --always --dirty)
LDFLAGS = -X github.com/xtls/xray-core/core.build=$(VERSION) -s -w -buildid=
PARAMS = -trimpath -ldflags "$(LDFLAGS)" -v
MAIN = ./main
PREFIX ?= $(shell go env GOPATH)
ifeq ($(GOOS),windows)
OUTPUT = $(NAME).exe
ADDITION = go build -o w$(NAME).exe -trimpath -ldflags "-H windowsgui $(LDFLAGS)" -v $(MAIN)
else
OUTPUT = $(NAME)
endif
ifeq ($(shell echo "$(GOARCH)" | grep -Pq "(mips|mipsle)" && echo true),true) #
ADDITION = GOMIPS=softfloat go build -o $(NAME)_softfloat -trimpath -ldflags "$(LDFLAGS)" -v $(MAIN)
endif
.PHONY: clean
build:
go build -o $(OUTPUT) $(PARAMS) $(MAIN)
$(ADDITION)
install:
go build -o $(PREFIX)/bin/$(OUTPUT) $(PARAMS) $(MAIN)
clean:
go clean -v -i $(PWD)
rm -f xray xray.exe wxray.exe xray_softfloat

View File

@@ -23,17 +23,18 @@
- Linux Script
- [XTLS/Xray-install](https://github.com/XTLS/Xray-install)
- Docker
- Official: [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core)
- [iamybj/docker-xray](https://hub.docker.com/r/iamybj/docker-xray)
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
- Web Panel
- [X-UI](https://github.com/FranzKafkaYu/x-ui), [X-UI-English](https://github.com/NidukaAkalanka/x-ui-english), [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [X-UI](https://github.com/diditra/x-ui)
- [X-UI-English](https://github.com/NidukaAkalanka/x-ui-english), [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [X-UI](https://github.com/diditra/x-ui)
- [Xray-UI](https://github.com/qist/xray-ui), [X-UI](https://github.com/sing-web/x-ui)
- [Hiddify](https://github.com/hiddify/hiddify-config)
- [Marzban](https://github.com/Gozargah/Marzban)
- [Libertea](https://github.com/VZiChoushaDui/Libertea)
- One Click
- [Xray-REALITY](https://github.com/zxcvos/Xray-script), [xray-reality](https://github.com/sajjaddg/xray-reality), [reality-ezpz](https://github.com/aleskxyz/reality-ezpz)
- [Xray-script](https://github.com/kirin10000/Xray-script), [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool)
- [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool)
- [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
- Magisk
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
@@ -56,6 +57,7 @@
- [REALITY (English)](https://cscot.pages.dev/2023/03/02/Xray-REALITY-tutorial/)
- [XTLS-Iran-Reality (English)](https://github.com/SasukeFreestyle/XTLS-Iran-Reality)
- [Xray REALITY with 'steal oneself' (English)](https://computerscot.github.io/vless-xtls-utls-reality-steal-oneself.html)
- [Xray with WireGuard inbound (English)](https://g800.pages.dev/wireguard)
## GUI Clients
@@ -123,16 +125,23 @@
## Compilation
### Windows
### Windows (PowerShell)
```bash
```powershell
$env:CGO_ENABLED=0
go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main
```
### Linux / macOS
```bash
go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
```
### Reproducible Releases
```bash
make
```
## Stargazers over time

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/commander/config.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/dispatcher/config.proto

View File

@@ -199,7 +199,7 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
return true
}
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" &&
destination.Address.Family().IsIP() && fkr0.IsIPInIPPool(destination.Address) {
fkr0.IsIPInIPPool(destination.Address) {
newError("Using sniffer ", protocolString, " since the fake DNS missed").WriteToLog(session.ExportIDToError(ctx))
return true
}
@@ -230,6 +230,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
content = new(session.Content)
ctx = session.ContextWithContent(ctx, content)
}
sniffingRequest := content.SniffingRequest
inbound, outbound := d.getLink(ctx)
if !sniffingRequest.Enabled {
@@ -253,7 +254,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
protocol = resComp.ProtocolForDomainResult()
}
isFakeIP := false
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && ob.Target.Address.Family().IsIP() && fkr0.IsIPInIPPool(ob.Target.Address) {
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && fkr0.IsIPInIPPool(ob.Target.Address) {
isFakeIP = true
}
if sniffingRequest.RouteOnly && protocol != "fakedns" && protocol != "fakedns+others" && !isFakeIP {
@@ -306,7 +307,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
protocol = resComp.ProtocolForDomainResult()
}
isFakeIP := false
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && ob.Target.Address.Family().IsIP() && fkr0.IsIPInIPPool(ob.Target.Address) {
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && fkr0.IsIPInIPPool(ob.Target.Address) {
isFakeIP = true
}
if sniffingRequest.RouteOnly && protocol != "fakedns" && protocol != "fakedns+others" && !isFakeIP {
@@ -366,7 +367,6 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
}
return contentResult, contentErr
}
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
ob := session.OutboundFromContext(ctx)
if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() {

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/dns/config.proto

View File

@@ -215,7 +215,8 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
errs = append(errs, err)
}
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch && err != dns.ErrEmptyResponse {
// 5 for RcodeRefused in miekg/dns, hardcode to reduce binary size
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch && err != dns.ErrEmptyResponse && dns.RCodeFromError(err) != 5 {
return nil, err
}
}

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/dns/fakedns/fakedns.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/log/command/config.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/log/config.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/metrics/config.proto

View File

@@ -0,0 +1,14 @@
package burst
import (
"math"
"time"
)
//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
const (
rttFailed = time.Duration(math.MaxInt64 - iota)
rttUntested
rttUnqualified
)

View File

@@ -0,0 +1,108 @@
package burst
import (
"context"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/signal/done"
"github.com/xtls/xray-core/features/extension"
"github.com/xtls/xray-core/features/outbound"
"google.golang.org/protobuf/proto"
"sync"
)
type Observer struct {
config *Config
ctx context.Context
statusLock sync.Mutex
hp *HealthPing
finished *done.Instance
ohm outbound.Manager
}
func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) {
return &observatory.ObservationResult{Status: o.createResult()}, nil
}
func (o *Observer) createResult() []*observatory.OutboundStatus {
var result []*observatory.OutboundStatus
o.hp.access.Lock()
defer o.hp.access.Unlock()
for name, value := range o.hp.Results {
status := observatory.OutboundStatus{
Alive: value.getStatistics().All != value.getStatistics().Fail,
Delay: value.getStatistics().Average.Milliseconds(),
LastErrorReason: "",
OutboundTag: name,
LastSeenTime: 0,
LastTryTime: 0,
HealthPing: &observatory.HealthPingMeasurementResult{
All: int64(value.getStatistics().All),
Fail: int64(value.getStatistics().Fail),
Deviation: int64(value.getStatistics().Deviation),
Average: int64(value.getStatistics().Average),
Max: int64(value.getStatistics().Max),
Min: int64(value.getStatistics().Min),
},
}
result = append(result, &status)
}
return result
}
func (o *Observer) Type() interface{} {
return extension.ObservatoryType()
}
func (o *Observer) Start() error {
if o.config != nil && len(o.config.SubjectSelector) != 0 {
o.finished = done.New()
o.hp.StartScheduler(func() ([]string, error) {
hs, ok := o.ohm.(outbound.HandlerSelector)
if !ok {
return nil, newError("outbound.Manager is not a HandlerSelector")
}
outbounds := hs.Select(o.config.SubjectSelector)
return outbounds, nil
})
}
return nil
}
func (o *Observer) Close() error {
if o.finished != nil {
o.hp.StopScheduler()
return o.finished.Close()
}
return nil
}
func New(ctx context.Context, config *Config) (*Observer, error) {
var outboundManager outbound.Manager
err := core.RequireFeatures(ctx, func(om outbound.Manager) {
outboundManager = om
})
if err != nil {
return nil, newError("Cannot get depended features").Base(err)
}
hp := NewHealthPing(ctx, config.PingConfig)
return &Observer{
config: config,
ctx: ctx,
ohm: outboundManager,
hp: hp,
}, nil
}
func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return New(ctx, config.(*Config))
}))
}

View File

@@ -0,0 +1,276 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/observatory/burst/config.proto
package burst
import (
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
// @Document The selectors for outbound under observation
SubjectSelector []string `protobuf:"bytes,2,rep,name=subject_selector,json=subjectSelector,proto3" json:"subject_selector,omitempty"`
PingConfig *HealthPingConfig `protobuf:"bytes,3,opt,name=ping_config,json=pingConfig,proto3" json:"ping_config,omitempty"`
}
func (x *Config) Reset() {
*x = Config{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_burst_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_app_observatory_burst_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && 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_app_observatory_burst_config_proto_rawDescGZIP(), []int{0}
}
func (x *Config) GetSubjectSelector() []string {
if x != nil {
return x.SubjectSelector
}
return nil
}
func (x *Config) GetPingConfig() *HealthPingConfig {
if x != nil {
return x.PingConfig
}
return nil
}
type HealthPingConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// destination url, need 204 for success return
// default https://connectivitycheck.gstatic.com/generate_204
Destination string `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"`
// connectivity check url
Connectivity string `protobuf:"bytes,2,opt,name=connectivity,proto3" json:"connectivity,omitempty"`
// health check interval, int64 values of time.Duration
Interval int64 `protobuf:"varint,3,opt,name=interval,proto3" json:"interval,omitempty"`
// sampling count is the amount of recent ping results which are kept for calculation
SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"`
// ping timeout, int64 values of time.Duration
Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"`
}
func (x *HealthPingConfig) Reset() {
*x = HealthPingConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_burst_config_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *HealthPingConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*HealthPingConfig) ProtoMessage() {}
func (x *HealthPingConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_burst_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use HealthPingConfig.ProtoReflect.Descriptor instead.
func (*HealthPingConfig) Descriptor() ([]byte, []int) {
return file_app_observatory_burst_config_proto_rawDescGZIP(), []int{1}
}
func (x *HealthPingConfig) GetDestination() string {
if x != nil {
return x.Destination
}
return ""
}
func (x *HealthPingConfig) GetConnectivity() string {
if x != nil {
return x.Connectivity
}
return ""
}
func (x *HealthPingConfig) GetInterval() int64 {
if x != nil {
return x.Interval
}
return 0
}
func (x *HealthPingConfig) GetSamplingCount() int32 {
if x != nil {
return x.SamplingCount
}
return 0
}
func (x *HealthPingConfig) GetTimeout() int64 {
if x != nil {
return x.Timeout
}
return 0
}
var File_app_observatory_burst_config_proto protoreflect.FileDescriptor
var file_app_observatory_burst_config_proto_rawDesc = []byte{
0x0a, 0x22, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
0x79, 0x2f, 0x62, 0x75, 0x72, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1f, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e,
0x62, 0x75, 0x72, 0x73, 0x74, 0x22, 0x87, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x29, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65,
0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x52, 0x0a, 0x0b, 0x70,
0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x31, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72,
0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
0xb4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69,
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69,
0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73,
0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07,
0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74,
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 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, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76,
0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x62, 0x75, 0x72, 0x73, 0x74, 0xaa, 0x02, 0x1a, 0x58, 0x72,
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
0x72, 0x79, 0x2e, 0x42, 0x75, 0x72, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_app_observatory_burst_config_proto_rawDescOnce sync.Once
file_app_observatory_burst_config_proto_rawDescData = file_app_observatory_burst_config_proto_rawDesc
)
func file_app_observatory_burst_config_proto_rawDescGZIP() []byte {
file_app_observatory_burst_config_proto_rawDescOnce.Do(func() {
file_app_observatory_burst_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_observatory_burst_config_proto_rawDescData)
})
return file_app_observatory_burst_config_proto_rawDescData
}
var file_app_observatory_burst_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_app_observatory_burst_config_proto_goTypes = []interface{}{
(*Config)(nil), // 0: xray.core.app.observatory.burst.Config
(*HealthPingConfig)(nil), // 1: xray.core.app.observatory.burst.HealthPingConfig
}
var file_app_observatory_burst_config_proto_depIdxs = []int32{
1, // 0: xray.core.app.observatory.burst.Config.ping_config:type_name -> xray.core.app.observatory.burst.HealthPingConfig
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_app_observatory_burst_config_proto_init() }
func file_app_observatory_burst_config_proto_init() {
if File_app_observatory_burst_config_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_app_observatory_burst_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
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_observatory_burst_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HealthPingConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_observatory_burst_config_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_app_observatory_burst_config_proto_goTypes,
DependencyIndexes: file_app_observatory_burst_config_proto_depIdxs,
MessageInfos: file_app_observatory_burst_config_proto_msgTypes,
}.Build()
File_app_observatory_burst_config_proto = out.File
file_app_observatory_burst_config_proto_rawDesc = nil
file_app_observatory_burst_config_proto_goTypes = nil
file_app_observatory_burst_config_proto_depIdxs = nil
}

View File

@@ -0,0 +1,29 @@
syntax = "proto3";
package xray.core.app.observatory.burst;
option csharp_namespace = "Xray.App.Observatory.Burst";
option go_package = "github.com/xtls/xray-core/app/observatory/burst";
option java_package = "com.xray.app.observatory.burst";
option java_multiple_files = true;
message Config {
/* @Document The selectors for outbound under observation
*/
repeated string subject_selector = 2;
HealthPingConfig ping_config = 3;
}
message HealthPingConfig {
// destination url, need 204 for success return
// default https://connectivitycheck.gstatic.com/generate_204
string destination = 1;
// connectivity check url
string connectivity = 2;
// health check interval, int64 values of time.Duration
int64 interval = 3;
// sampling count is the amount of recent ping results which are kept for calculation
int32 samplingCount = 4;
// ping timeout, int64 values of time.Duration
int64 timeout = 5;
}

View File

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

View File

@@ -0,0 +1,244 @@
package burst
import (
"context"
"fmt"
"strings"
"sync"
"time"
"github.com/xtls/xray-core/common/dice"
)
// HealthPingSettings holds settings for health Checker
type HealthPingSettings struct {
Destination string `json:"destination"`
Connectivity string `json:"connectivity"`
Interval time.Duration `json:"interval"`
SamplingCount int `json:"sampling"`
Timeout time.Duration `json:"timeout"`
}
// HealthPing is the health checker for balancers
type HealthPing struct {
ctx context.Context
access sync.Mutex
ticker *time.Ticker
tickerClose chan struct{}
Settings *HealthPingSettings
Results map[string]*HealthPingRTTS
}
// NewHealthPing creates a new HealthPing with settings
func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing {
settings := &HealthPingSettings{}
if config != nil {
settings = &HealthPingSettings{
Connectivity: strings.TrimSpace(config.Connectivity),
Destination: strings.TrimSpace(config.Destination),
Interval: time.Duration(config.Interval),
SamplingCount: int(config.SamplingCount),
Timeout: time.Duration(config.Timeout),
}
}
if settings.Destination == "" {
// Destination URL, need 204 for success return default to chromium
// https://github.com/chromium/chromium/blob/main/components/safety_check/url_constants.cc#L10
// https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/safety_check/url_constants.cc#10
settings.Destination = "https://connectivitycheck.gstatic.com/generate_204"
}
if settings.Interval == 0 {
settings.Interval = time.Duration(1) * time.Minute
} else if settings.Interval < 10 {
newError("health check interval is too small, 10s is applied").AtWarning().WriteToLog()
settings.Interval = time.Duration(10) * time.Second
}
if settings.SamplingCount <= 0 {
settings.SamplingCount = 10
}
if settings.Timeout <= 0 {
// results are saved after all health pings finish,
// a larger timeout could possibly makes checks run longer
settings.Timeout = time.Duration(5) * time.Second
}
return &HealthPing{
ctx: ctx,
Settings: settings,
Results: nil,
}
}
// StartScheduler implements the HealthChecker
func (h *HealthPing) StartScheduler(selector func() ([]string, error)) {
if h.ticker != nil {
return
}
interval := h.Settings.Interval * time.Duration(h.Settings.SamplingCount)
ticker := time.NewTicker(interval)
tickerClose := make(chan struct{})
h.ticker = ticker
h.tickerClose = tickerClose
go func() {
for {
go func() {
tags, err := selector()
if err != nil {
newError("error select outbounds for scheduled health check: ", err).AtWarning().WriteToLog()
return
}
h.doCheck(tags, interval, h.Settings.SamplingCount)
h.Cleanup(tags)
}()
select {
case <-ticker.C:
continue
case <-tickerClose:
return
}
}
}()
}
// StopScheduler implements the HealthChecker
func (h *HealthPing) StopScheduler() {
if h.ticker == nil {
return
}
h.ticker.Stop()
h.ticker = nil
close(h.tickerClose)
h.tickerClose = nil
}
// Check implements the HealthChecker
func (h *HealthPing) Check(tags []string) error {
if len(tags) == 0 {
return nil
}
newError("perform one-time health check for tags ", tags).AtInfo().WriteToLog()
h.doCheck(tags, 0, 1)
return nil
}
type rtt struct {
handler string
value time.Duration
}
// doCheck performs the 'rounds' amount checks in given 'duration'. You should make
// sure all tags are valid for current balancer
func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int) {
count := len(tags) * rounds
if count == 0 {
return
}
ch := make(chan *rtt, count)
for _, tag := range tags {
handler := tag
client := newPingClient(
h.ctx,
h.Settings.Destination,
h.Settings.Timeout,
handler,
)
for i := 0; i < rounds; i++ {
delay := time.Duration(0)
if duration > 0 {
delay = time.Duration(dice.Roll(int(duration)))
}
time.AfterFunc(delay, func() {
newError("checking ", handler).AtDebug().WriteToLog()
delay, err := client.MeasureDelay()
if err == nil {
ch <- &rtt{
handler: handler,
value: delay,
}
return
}
if !h.checkConnectivity() {
newError("network is down").AtWarning().WriteToLog()
ch <- &rtt{
handler: handler,
value: 0,
}
return
}
newError(fmt.Sprintf(
"error ping %s with %s: %s",
h.Settings.Destination,
handler,
err,
)).AtWarning().WriteToLog()
ch <- &rtt{
handler: handler,
value: rttFailed,
}
})
}
}
for i := 0; i < count; i++ {
rtt := <-ch
if rtt.value > 0 {
// should not put results when network is down
h.PutResult(rtt.handler, rtt.value)
}
}
}
// PutResult put a ping rtt to results
func (h *HealthPing) PutResult(tag string, rtt time.Duration) {
h.access.Lock()
defer h.access.Unlock()
if h.Results == nil {
h.Results = make(map[string]*HealthPingRTTS)
}
r, ok := h.Results[tag]
if !ok {
// validity is 2 times to sampling period, since the check are
// distributed in the time line randomly, in extreme cases,
// previous checks are distributed on the left, and latters
// on the right
validity := h.Settings.Interval * time.Duration(h.Settings.SamplingCount) * 2
r = NewHealthPingResult(h.Settings.SamplingCount, validity)
h.Results[tag] = r
}
r.Put(rtt)
}
// Cleanup removes results of removed handlers,
// tags should be all valid tags of the Balancer now
func (h *HealthPing) Cleanup(tags []string) {
h.access.Lock()
defer h.access.Unlock()
for tag := range h.Results {
found := false
for _, v := range tags {
if tag == v {
found = true
break
}
}
if !found {
delete(h.Results, tag)
}
}
}
// checkConnectivity checks the network connectivity, it returns
// true if network is good or "connectivity check url" not set
func (h *HealthPing) checkConnectivity() bool {
if h.Settings.Connectivity == "" {
return true
}
tester := newDirectPingClient(
h.Settings.Connectivity,
h.Settings.Timeout,
)
if _, err := tester.MeasureDelay(); err != nil {
return false
}
return true
}

View File

@@ -0,0 +1,143 @@
package burst
import (
"math"
"time"
)
// HealthPingStats is the statistics of HealthPingRTTS
type HealthPingStats struct {
All int
Fail int
Deviation time.Duration
Average time.Duration
Max time.Duration
Min time.Duration
}
// HealthPingRTTS holds ping rtts for health Checker
type HealthPingRTTS struct {
idx int
cap int
validity time.Duration
rtts []*pingRTT
lastUpdateAt time.Time
stats *HealthPingStats
}
type pingRTT struct {
time time.Time
value time.Duration
}
// NewHealthPingResult returns a *HealthPingResult with specified capacity
func NewHealthPingResult(cap int, validity time.Duration) *HealthPingRTTS {
return &HealthPingRTTS{cap: cap, validity: validity}
}
// Get gets statistics of the HealthPingRTTS
func (h *HealthPingRTTS) Get() *HealthPingStats {
return h.getStatistics()
}
// GetWithCache get statistics and write cache for next call
// Make sure use Mutex.Lock() before calling it, RWMutex.RLock()
// is not an option since it writes cache
func (h *HealthPingRTTS) GetWithCache() *HealthPingStats {
lastPutAt := h.rtts[h.idx].time
now := time.Now()
if h.stats == nil || h.lastUpdateAt.Before(lastPutAt) || h.findOutdated(now) >= 0 {
h.stats = h.getStatistics()
h.lastUpdateAt = now
}
return h.stats
}
// Put puts a new rtt to the HealthPingResult
func (h *HealthPingRTTS) Put(d time.Duration) {
if h.rtts == nil {
h.rtts = make([]*pingRTT, h.cap)
for i := 0; i < h.cap; i++ {
h.rtts[i] = &pingRTT{}
}
h.idx = -1
}
h.idx = h.calcIndex(1)
now := time.Now()
h.rtts[h.idx].time = now
h.rtts[h.idx].value = d
}
func (h *HealthPingRTTS) calcIndex(step int) int {
idx := h.idx
idx += step
if idx >= h.cap {
idx %= h.cap
}
return idx
}
func (h *HealthPingRTTS) getStatistics() *HealthPingStats {
stats := &HealthPingStats{}
stats.Fail = 0
stats.Max = 0
stats.Min = rttFailed
sum := time.Duration(0)
cnt := 0
validRTTs := make([]time.Duration, 0)
for _, rtt := range h.rtts {
switch {
case rtt.value == 0 || time.Since(rtt.time) > h.validity:
continue
case rtt.value == rttFailed:
stats.Fail++
continue
}
cnt++
sum += rtt.value
validRTTs = append(validRTTs, rtt.value)
if stats.Max < rtt.value {
stats.Max = rtt.value
}
if stats.Min > rtt.value {
stats.Min = rtt.value
}
}
stats.All = cnt + stats.Fail
if cnt == 0 {
stats.Min = 0
return stats
}
stats.Average = time.Duration(int(sum) / cnt)
var std float64
if cnt < 2 {
// no enough data for standard deviation, we assume it's half of the average rtt
// if we don't do this, standard deviation of 1 round tested nodes is 0, will always
// selected before 2 or more rounds tested nodes
std = float64(stats.Average / 2)
} else {
variance := float64(0)
for _, rtt := range validRTTs {
variance += math.Pow(float64(rtt-stats.Average), 2)
}
std = math.Sqrt(variance / float64(cnt))
}
stats.Deviation = time.Duration(std)
return stats
}
func (h *HealthPingRTTS) findOutdated(now time.Time) int {
for i := h.cap - 1; i < 2*h.cap; i++ {
// from oldest to latest
idx := h.calcIndex(i)
validity := h.rtts[idx].time.Add(h.validity)
if h.lastUpdateAt.After(validity) {
return idx
}
if validity.Before(now) {
return idx
}
}
return -1
}

View File

@@ -0,0 +1,106 @@
package burst_test
import (
"math"
reflect "reflect"
"testing"
"time"
"github.com/xtls/xray-core/app/observatory/burst"
)
func TestHealthPingResults(t *testing.T) {
rtts := []int64{60, 140, 60, 140, 60, 60, 140, 60, 140}
hr := burst.NewHealthPingResult(4, time.Hour)
for _, rtt := range rtts {
hr.Put(time.Duration(rtt))
}
rttFailed := time.Duration(math.MaxInt64)
expected := &burst.HealthPingStats{
All: 4,
Fail: 0,
Deviation: 40,
Average: 100,
Max: 140,
Min: 60,
}
actual := hr.Get()
if !reflect.DeepEqual(expected, actual) {
t.Errorf("expected: %v, actual: %v", expected, actual)
}
hr.Put(rttFailed)
hr.Put(rttFailed)
expected.Fail = 2
actual = hr.Get()
if !reflect.DeepEqual(expected, actual) {
t.Errorf("failed half-failures test, expected: %v, actual: %v", expected, actual)
}
hr.Put(rttFailed)
hr.Put(rttFailed)
expected = &burst.HealthPingStats{
All: 4,
Fail: 4,
Deviation: 0,
Average: 0,
Max: 0,
Min: 0,
}
actual = hr.Get()
if !reflect.DeepEqual(expected, actual) {
t.Errorf("failed all-failures test, expected: %v, actual: %v", expected, actual)
}
}
func TestHealthPingResultsIgnoreOutdated(t *testing.T) {
rtts := []int64{60, 140, 60, 140}
hr := burst.NewHealthPingResult(4, time.Duration(10)*time.Millisecond)
for i, rtt := range rtts {
if i == 2 {
// wait for previous 2 outdated
time.Sleep(time.Duration(10) * time.Millisecond)
}
hr.Put(time.Duration(rtt))
}
hr.Get()
expected := &burst.HealthPingStats{
All: 2,
Fail: 0,
Deviation: 40,
Average: 100,
Max: 140,
Min: 60,
}
actual := hr.Get()
if !reflect.DeepEqual(expected, actual) {
t.Errorf("failed 'half-outdated' test, expected: %v, actual: %v", expected, actual)
}
// wait for all outdated
time.Sleep(time.Duration(10) * time.Millisecond)
expected = &burst.HealthPingStats{
All: 0,
Fail: 0,
Deviation: 0,
Average: 0,
Max: 0,
Min: 0,
}
actual = hr.Get()
if !reflect.DeepEqual(expected, actual) {
t.Errorf("failed 'outdated / not-tested' test, expected: %v, actual: %v", expected, actual)
}
hr.Put(time.Duration(60))
expected = &burst.HealthPingStats{
All: 1,
Fail: 0,
// 1 sample, std=0.5rtt
Deviation: 30,
Average: 60,
Max: 60,
Min: 60,
}
actual = hr.Get()
if !reflect.DeepEqual(expected, actual) {
t.Errorf("expected: %v, actual: %v", expected, actual)
}
}

View File

@@ -0,0 +1,69 @@
package burst
import (
"context"
"net/http"
"time"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/transport/internet/tagged"
)
type pingClient struct {
destination string
httpClient *http.Client
}
func newPingClient(ctx context.Context, destination string, timeout time.Duration, handler string) *pingClient {
return &pingClient{
destination: destination,
httpClient: newHTTPClient(ctx, handler, timeout),
}
}
func newDirectPingClient(destination string, timeout time.Duration) *pingClient {
return &pingClient{
destination: destination,
httpClient: &http.Client{Timeout: timeout},
}
}
func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration) *http.Client {
tr := &http.Transport{
DisableKeepAlives: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
return tagged.Dialer(ctxv, dest, handler)
},
}
return &http.Client{
Transport: tr,
Timeout: timeout,
// don't follow redirect
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}
// MeasureDelay returns the delay time of the request to dest
func (s *pingClient) MeasureDelay() (time.Duration, error) {
if s.httpClient == nil {
panic("pingClient no initialized")
}
req, err := http.NewRequest(http.MethodHead, s.destination, nil)
if err != nil {
return rttFailed, err
}
start := time.Now()
resp, err := s.httpClient.Do(req)
if err != nil {
return rttFailed, err
}
// don't wait for body
resp.Body.Close()
return time.Since(start), nil
}

View File

@@ -1,6 +1,3 @@
//go:build !confonly
// +build !confonly
package command
import (

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/observatory/command/command.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/observatory/config.proto
@@ -67,6 +67,93 @@ func (x *ObservationResult) GetStatus() []*OutboundStatus {
return nil
}
type HealthPingMeasurementResult struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
All int64 `protobuf:"varint,1,opt,name=all,proto3" json:"all,omitempty"`
Fail int64 `protobuf:"varint,2,opt,name=fail,proto3" json:"fail,omitempty"`
Deviation int64 `protobuf:"varint,3,opt,name=deviation,proto3" json:"deviation,omitempty"`
Average int64 `protobuf:"varint,4,opt,name=average,proto3" json:"average,omitempty"`
Max int64 `protobuf:"varint,5,opt,name=max,proto3" json:"max,omitempty"`
Min int64 `protobuf:"varint,6,opt,name=min,proto3" json:"min,omitempty"`
}
func (x *HealthPingMeasurementResult) Reset() {
*x = HealthPingMeasurementResult{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_config_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *HealthPingMeasurementResult) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*HealthPingMeasurementResult) ProtoMessage() {}
func (x *HealthPingMeasurementResult) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use HealthPingMeasurementResult.ProtoReflect.Descriptor instead.
func (*HealthPingMeasurementResult) Descriptor() ([]byte, []int) {
return file_app_observatory_config_proto_rawDescGZIP(), []int{1}
}
func (x *HealthPingMeasurementResult) GetAll() int64 {
if x != nil {
return x.All
}
return 0
}
func (x *HealthPingMeasurementResult) GetFail() int64 {
if x != nil {
return x.Fail
}
return 0
}
func (x *HealthPingMeasurementResult) GetDeviation() int64 {
if x != nil {
return x.Deviation
}
return 0
}
func (x *HealthPingMeasurementResult) GetAverage() int64 {
if x != nil {
return x.Average
}
return 0
}
func (x *HealthPingMeasurementResult) GetMax() int64 {
if x != nil {
return x.Max
}
return 0
}
func (x *HealthPingMeasurementResult) GetMin() int64 {
if x != nil {
return x.Min
}
return 0
}
type OutboundStatus struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -91,12 +178,13 @@ type OutboundStatus struct {
// @Document The time this outbound is tried
// @Type id.outboundTag
LastTryTime int64 `protobuf:"varint,6,opt,name=last_try_time,json=lastTryTime,proto3" json:"last_try_time,omitempty"`
HealthPing *HealthPingMeasurementResult `protobuf:"bytes,7,opt,name=health_ping,json=healthPing,proto3" json:"health_ping,omitempty"`
}
func (x *OutboundStatus) Reset() {
*x = OutboundStatus{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_config_proto_msgTypes[1]
mi := &file_app_observatory_config_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -109,7 +197,7 @@ func (x *OutboundStatus) String() string {
func (*OutboundStatus) ProtoMessage() {}
func (x *OutboundStatus) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[1]
mi := &file_app_observatory_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -122,7 +210,7 @@ func (x *OutboundStatus) ProtoReflect() protoreflect.Message {
// Deprecated: Use OutboundStatus.ProtoReflect.Descriptor instead.
func (*OutboundStatus) Descriptor() ([]byte, []int) {
return file_app_observatory_config_proto_rawDescGZIP(), []int{1}
return file_app_observatory_config_proto_rawDescGZIP(), []int{2}
}
func (x *OutboundStatus) GetAlive() bool {
@@ -167,6 +255,13 @@ func (x *OutboundStatus) GetLastTryTime() int64 {
return 0
}
func (x *OutboundStatus) GetHealthPing() *HealthPingMeasurementResult {
if x != nil {
return x.HealthPing
}
return nil
}
type ProbeResult struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -187,7 +282,7 @@ type ProbeResult struct {
func (x *ProbeResult) Reset() {
*x = ProbeResult{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_config_proto_msgTypes[2]
mi := &file_app_observatory_config_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -200,7 +295,7 @@ func (x *ProbeResult) String() string {
func (*ProbeResult) ProtoMessage() {}
func (x *ProbeResult) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[2]
mi := &file_app_observatory_config_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -213,7 +308,7 @@ func (x *ProbeResult) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProbeResult.ProtoReflect.Descriptor instead.
func (*ProbeResult) Descriptor() ([]byte, []int) {
return file_app_observatory_config_proto_rawDescGZIP(), []int{2}
return file_app_observatory_config_proto_rawDescGZIP(), []int{3}
}
func (x *ProbeResult) GetAlive() bool {
@@ -250,7 +345,7 @@ type Intensity struct {
func (x *Intensity) Reset() {
*x = Intensity{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_config_proto_msgTypes[3]
mi := &file_app_observatory_config_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -263,7 +358,7 @@ func (x *Intensity) String() string {
func (*Intensity) ProtoMessage() {}
func (x *Intensity) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[3]
mi := &file_app_observatory_config_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -276,7 +371,7 @@ func (x *Intensity) ProtoReflect() protoreflect.Message {
// Deprecated: Use Intensity.ProtoReflect.Descriptor instead.
func (*Intensity) Descriptor() ([]byte, []int) {
return file_app_observatory_config_proto_rawDescGZIP(), []int{3}
return file_app_observatory_config_proto_rawDescGZIP(), []int{4}
}
func (x *Intensity) GetProbeInterval() uint32 {
@@ -301,7 +396,7 @@ type Config struct {
func (x *Config) Reset() {
*x = Config{}
if protoimpl.UnsafeEnabled {
mi := &file_app_observatory_config_proto_msgTypes[4]
mi := &file_app_observatory_config_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -314,7 +409,7 @@ func (x *Config) String() string {
func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[4]
mi := &file_app_observatory_config_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -327,7 +422,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_app_observatory_config_proto_rawDescGZIP(), []int{4}
return file_app_observatory_config_proto_rawDescGZIP(), []int{5}
}
func (x *Config) GetSubjectSelector() []string {
@@ -370,47 +465,62 @@ var file_app_observatory_config_proto_rawDesc = []byte{
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f,
0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
0x73, 0x22, 0xd5, 0x01, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65,
0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79,
0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72,
0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x61, 0x73,
0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c,
0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x04, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12,
0x24, 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x5f, 0x74, 0x69, 0x6d,
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65,
0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x72,
0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6c, 0x61,
0x73, 0x74, 0x54, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x65, 0x0a, 0x0b, 0x50, 0x72, 0x6f,
0x62, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x76,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x14,
0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64,
0x65, 0x6c, 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0f, 0x6c, 0x61, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e,
0x22, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a,
0x0e, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6e, 0x74, 0x65,
0x72, 0x76, 0x61, 0x6c, 0x22, 0xa6, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x29, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a, 0x65,
0x63, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72,
0x6f, 0x62, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
0x72, 0x6f, 0x62, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x62, 0x65,
0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
0x0d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2d,
0x0a, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72,
0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x65, 0x6e, 0x61, 0x62,
0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x5e, 0x0a,
0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62,
0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x01, 0x5a, 0x29, 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, 0x6f, 0x62, 0x73, 0x65, 0x72,
0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0xaa, 0x02, 0x14, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x73, 0x22, 0x9f, 0x01, 0x0a, 0x1b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67,
0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c,
0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03,
0x61, 0x6c, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
0x03, 0x52, 0x04, 0x66, 0x61, 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65,
0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x12,
0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x61,
0x78, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03,
0x6d, 0x69, 0x6e, 0x22, 0xae, 0x02, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x65, 0x6c,
0x61, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c,
0x61, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21,
0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x04,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61,
0x67, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x5f, 0x74,
0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53,
0x65, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x5f,
0x74, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
0x6c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x57, 0x0a, 0x0b, 0x68,
0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x36, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x48, 0x65, 0x61,
0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65,
0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68,
0x50, 0x69, 0x6e, 0x67, 0x22, 0x65, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6c,
0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x12,
0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65,
0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74,
0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x32, 0x0a, 0x09, 0x49,
0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x62,
0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
0x52, 0x0d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22,
0xa6, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x75,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02,
0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x6c,
0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x5f, 0x75,
0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x55,
0x72, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x62,
0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x65, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18,
0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6e,
0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x5e, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61,
0x74, 0x6f, 0x72, 0x79, 0x50, 0x01, 0x5a, 0x29, 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, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
0x79, 0xaa, 0x02, 0x14, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73,
0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -425,21 +535,23 @@ func file_app_observatory_config_proto_rawDescGZIP() []byte {
return file_app_observatory_config_proto_rawDescData
}
var file_app_observatory_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_app_observatory_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_app_observatory_config_proto_goTypes = []interface{}{
(*ObservationResult)(nil), // 0: xray.core.app.observatory.ObservationResult
(*OutboundStatus)(nil), // 1: xray.core.app.observatory.OutboundStatus
(*ProbeResult)(nil), // 2: xray.core.app.observatory.ProbeResult
(*Intensity)(nil), // 3: xray.core.app.observatory.Intensity
(*Config)(nil), // 4: xray.core.app.observatory.Config
(*HealthPingMeasurementResult)(nil), // 1: xray.core.app.observatory.HealthPingMeasurementResult
(*OutboundStatus)(nil), // 2: xray.core.app.observatory.OutboundStatus
(*ProbeResult)(nil), // 3: xray.core.app.observatory.ProbeResult
(*Intensity)(nil), // 4: xray.core.app.observatory.Intensity
(*Config)(nil), // 5: xray.core.app.observatory.Config
}
var file_app_observatory_config_proto_depIdxs = []int32{
1, // 0: xray.core.app.observatory.ObservationResult.status:type_name -> xray.core.app.observatory.OutboundStatus
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
2, // 0: xray.core.app.observatory.ObservationResult.status:type_name -> xray.core.app.observatory.OutboundStatus
1, // 1: xray.core.app.observatory.OutboundStatus.health_ping:type_name -> xray.core.app.observatory.HealthPingMeasurementResult
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_app_observatory_config_proto_init() }
@@ -461,7 +573,7 @@ func file_app_observatory_config_proto_init() {
}
}
file_app_observatory_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OutboundStatus); i {
switch v := v.(*HealthPingMeasurementResult); i {
case 0:
return &v.state
case 1:
@@ -473,7 +585,7 @@ func file_app_observatory_config_proto_init() {
}
}
file_app_observatory_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ProbeResult); i {
switch v := v.(*OutboundStatus); i {
case 0:
return &v.state
case 1:
@@ -485,7 +597,7 @@ func file_app_observatory_config_proto_init() {
}
}
file_app_observatory_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Intensity); i {
switch v := v.(*ProbeResult); i {
case 0:
return &v.state
case 1:
@@ -497,6 +609,18 @@ func file_app_observatory_config_proto_init() {
}
}
file_app_observatory_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Intensity); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
@@ -515,7 +639,7 @@ func file_app_observatory_config_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_observatory_config_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -10,6 +10,15 @@ message ObservationResult {
repeated OutboundStatus status = 1;
}
message HealthPingMeasurementResult {
int64 all = 1;
int64 fail = 2;
int64 deviation = 3;
int64 average = 4;
int64 max = 5;
int64 min = 6;
}
message OutboundStatus{
/* @Document Whether this outbound is usable
@Restriction ReadOnlyForUser
@@ -36,6 +45,8 @@ message OutboundStatus{
@Type id.outboundTag
*/
int64 last_try_time = 6;
HealthPingMeasurementResult health_ping = 7;
}
message ProbeResult{

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/policy/config.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/proxyman/command/command.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/proxyman/config.proto

View File

@@ -229,6 +229,10 @@ func (h *Handler) Address() net.Address {
return h.senderSettings.Via.AsAddress()
}
func (h *Handler) DestIpAddress() net.IP {
return internet.DestIpAddress()
}
// Dial implements internet.Dialer.
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
if h.senderSettings != nil {

View File

@@ -2,9 +2,14 @@ package outbound_test
import (
"context"
"fmt"
"sync"
"sync/atomic"
"testing"
"time"
"github.com/xtls/xray-core/app/policy"
"github.com/xtls/xray-core/app/proxyman"
. "github.com/xtls/xray-core/app/proxyman/outbound"
"github.com/xtls/xray-core/app/stats"
"github.com/xtls/xray-core/common/net"
@@ -78,3 +83,91 @@ func TestOutboundWithStatCounter(t *testing.T) {
t.Errorf("Expected conn to be CounterConnection")
}
}
func TestTagsCache(t *testing.T) {
test_duration := 10 * time.Second
threads_num := 50
delay := 10 * time.Millisecond
tags_prefix := "node"
tags := sync.Map{}
counter := atomic.Uint64{}
ohm, err := New(context.Background(), &proxyman.OutboundConfig{})
if err != nil {
t.Error("failed to create outbound handler manager")
}
config := &core.Config{
App: []*serial.TypedMessage{},
}
v, _ := core.New(config)
v.AddFeature(ohm)
ctx := context.WithValue(context.Background(), xrayKey, v)
stop_add_rm := false
wg_add_rm := sync.WaitGroup{}
addHandlers := func() {
defer wg_add_rm.Done()
for !stop_add_rm {
time.Sleep(delay)
idx := counter.Add(1)
tag := fmt.Sprintf("%s%d", tags_prefix, idx)
cfg := &core.OutboundHandlerConfig{
Tag: tag,
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
}
if h, err := NewHandler(ctx, cfg); err == nil {
if err := ohm.AddHandler(ctx, h); err == nil {
// t.Log("add handler:", tag)
tags.Store(tag, nil)
} else {
t.Error("failed to add handler:", tag)
}
} else {
t.Error("failed to create handler:", tag)
}
}
}
rmHandlers := func() {
defer wg_add_rm.Done()
for !stop_add_rm {
time.Sleep(delay)
tags.Range(func(key interface{}, value interface{}) bool {
if _, ok := tags.LoadAndDelete(key); ok {
// t.Log("remove handler:", key)
ohm.RemoveHandler(ctx, key.(string))
return false
}
return true
})
}
}
selectors := []string{tags_prefix}
wg_get := sync.WaitGroup{}
stop_get := false
getTags := func() {
defer wg_get.Done()
for !stop_get {
time.Sleep(delay)
_ = ohm.Select(selectors)
// t.Logf("get tags: %v", tag)
}
}
for i := 0; i < threads_num; i++ {
wg_add_rm.Add(2)
go rmHandlers()
go addHandlers()
wg_get.Add(1)
go getTags()
}
time.Sleep(test_duration)
stop_add_rm = true
wg_add_rm.Wait()
stop_get = true
wg_get.Wait()
}

View File

@@ -4,6 +4,7 @@ package outbound
import (
"context"
"sort"
"strings"
"sync"
@@ -21,12 +22,14 @@ type Manager struct {
taggedHandler map[string]outbound.Handler
untaggedHandlers []outbound.Handler
running bool
tagsCache *sync.Map
}
// New creates a new Manager.
func New(ctx context.Context, config *proxyman.OutboundConfig) (*Manager, error) {
m := &Manager{
taggedHandler: make(map[string]outbound.Handler),
tagsCache: &sync.Map{},
}
return m, nil
}
@@ -103,6 +106,8 @@ func (m *Manager) AddHandler(ctx context.Context, handler outbound.Handler) erro
m.access.Lock()
defer m.access.Unlock()
m.tagsCache = &sync.Map{}
if m.defaultHandler == nil {
m.defaultHandler = handler
}
@@ -132,6 +137,8 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
m.access.Lock()
defer m.access.Unlock()
m.tagsCache = &sync.Map{}
delete(m.taggedHandler, tag)
if m.defaultHandler != nil && m.defaultHandler.Tag() == tag {
m.defaultHandler = nil
@@ -142,24 +149,29 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
// Select implements outbound.HandlerSelector.
func (m *Manager) Select(selectors []string) []string {
key := strings.Join(selectors, ",")
if cache, ok := m.tagsCache.Load(key); ok {
return cache.([]string)
}
m.access.RLock()
defer m.access.RUnlock()
tags := make([]string, 0, len(selectors))
for tag := range m.taggedHandler {
match := false
for _, selector := range selectors {
if strings.HasPrefix(tag, selector) {
match = true
tags = append(tags, tag)
break
}
}
if match {
tags = append(tags, tag)
}
}
sort.Strings(tags)
m.tagsCache.Store(key, tags)
return tags
}

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/reverse/config.proto

View File

@@ -2,8 +2,8 @@ package router
import (
"context"
sync "sync"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/features/extension"
"github.com/xtls/xray-core/features/outbound"
)
@@ -12,34 +12,59 @@ type BalancingStrategy interface {
PickOutbound([]string) string
}
type RandomStrategy struct{}
type BalancingPrincipleTarget interface {
GetPrincipleTarget([]string) []string
}
func (s *RandomStrategy) PickOutbound(tags []string) string {
type RoundRobinStrategy struct {
mu sync.Mutex
index int
}
func (s *RoundRobinStrategy) PickOutbound(tags []string) string {
n := len(tags)
if n == 0 {
panic("0 tags")
}
return tags[dice.Roll(n)]
s.mu.Lock()
defer s.mu.Unlock()
tag := tags[s.index%n]
s.index = (s.index + 1) % n
return tag
}
type Balancer struct {
selectors []string
strategy BalancingStrategy
ohm outbound.Manager
fallbackTag string
override override
}
// PickOutbound picks the tag of a outbound
func (b *Balancer) PickOutbound() (string, error) {
hs, ok := b.ohm.(outbound.HandlerSelector)
if !ok {
return "", newError("outbound.Manager is not a HandlerSelector")
candidates, err := b.SelectOutbounds()
if err != nil {
if b.fallbackTag != "" {
newError("fallback to [", b.fallbackTag, "], due to error: ", err).AtInfo().WriteToLog()
return b.fallbackTag, nil
}
tags := hs.Select(b.selectors)
if len(tags) == 0 {
return "", newError("no available outbounds selected")
return "", err
}
var tag string
if o := b.override.Get(); o != "" {
tag = o
} else {
tag = b.strategy.PickOutbound(candidates)
}
tag := b.strategy.PickOutbound(tags)
if tag == "" {
if b.fallbackTag != "" {
newError("fallback to [", b.fallbackTag, "], due to empty tag returned").AtInfo().WriteToLog()
return b.fallbackTag, nil
}
// will use default handler
return "", newError("balancing strategy returns empty tag")
}
return tag, nil
@@ -50,3 +75,45 @@ func (b *Balancer) InjectContext(ctx context.Context) {
contextReceiver.InjectContext(ctx)
}
}
// SelectOutbounds select outbounds with selectors of the Balancer
func (b *Balancer) SelectOutbounds() ([]string, error) {
hs, ok := b.ohm.(outbound.HandlerSelector)
if !ok {
return nil, newError("outbound.Manager is not a HandlerSelector")
}
tags := hs.Select(b.selectors)
return tags, nil
}
// GetPrincipleTarget implements routing.BalancerPrincipleTarget
func (r *Router) GetPrincipleTarget(tag string) ([]string, error) {
if b, ok := r.balancers[tag]; ok {
if s, ok := b.strategy.(BalancingPrincipleTarget); ok {
candidates, err := b.SelectOutbounds()
if err != nil {
return nil, newError("unable to select outbounds").Base(err)
}
return s.GetPrincipleTarget(candidates), nil
}
return nil, newError("unsupported GetPrincipleTarget")
}
return nil, newError("cannot find tag")
}
// SetOverrideTarget implements routing.BalancerOverrider
func (r *Router) SetOverrideTarget(tag, target string) error {
if b, ok := r.balancers[tag]; ok {
b.override.Put(target)
return nil
}
return newError("cannot find tag")
}
// GetOverrideTarget implements routing.BalancerOverrider
func (r *Router) GetOverrideTarget(tag string) (string, error) {
if b, ok := r.balancers[tag]; ok {
return b.override.Get(), nil
}
return "", newError("cannot find tag")
}

View File

@@ -0,0 +1,50 @@
package router
import (
sync "sync"
)
func (r *Router) OverrideBalancer(balancer string, target string) error {
var b *Balancer
for tag, bl := range r.balancers {
if tag == balancer {
b = bl
break
}
}
if b == nil {
return newError("balancer '", balancer, "' not found")
}
b.override.Put(target)
return nil
}
type overrideSettings struct {
target string
}
type override struct {
access sync.RWMutex
settings overrideSettings
}
// Get gets the override settings
func (o *override) Get() string {
o.access.RLock()
defer o.access.RUnlock()
return o.settings.target
}
// Put updates the override settings
func (o *override) Put(target string) {
o.access.Lock()
defer o.access.Unlock()
o.settings.target = target
}
// Clear clears the override settings
func (o *override) Clear() {
o.access.Lock()
defer o.access.Unlock()
o.settings.target = ""
}

View File

@@ -19,6 +19,41 @@ type routingServer struct {
routingStats stats.Channel
}
func (s *routingServer) GetBalancerInfo(ctx context.Context, request *GetBalancerInfoRequest) (*GetBalancerInfoResponse, error) {
var ret GetBalancerInfoResponse
ret.Balancer = &BalancerMsg{}
if bo, ok := s.router.(routing.BalancerOverrider); ok {
{
res, err := bo.GetOverrideTarget(request.GetTag())
if err != nil {
return nil, err
}
ret.Balancer.Override = &OverrideInfo{
Target: res,
}
}
}
if pt, ok := s.router.(routing.BalancerPrincipleTarget); ok {
{
res, err := pt.GetPrincipleTarget(request.GetTag())
if err != nil {
newError("unable to obtain principle target").Base(err).AtInfo().WriteToLog()
} else {
ret.Balancer.PrincipleTarget = &PrincipleTargetInfo{Tag: res}
}
}
}
return &ret, nil
}
func (s *routingServer) OverrideBalancerTarget(ctx context.Context, request *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error) {
if bo, ok := s.router.(routing.BalancerOverrider); ok {
return &OverrideBalancerTargetResponse{}, bo.SetOverrideTarget(request.BalancerTag, request.Target)
}
return nil, newError("unsupported router implementation")
}
// NewRoutingServer creates a statistics service with statistics manager.
func NewRoutingServer(router routing.Router, routingStats stats.Channel) RoutingServiceServer {
return &routingServer{

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/router/command/command.proto
@@ -294,6 +294,342 @@ func (x *TestRouteRequest) GetPublishResult() bool {
return false
}
type PrincipleTargetInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Tag []string `protobuf:"bytes,1,rep,name=tag,proto3" json:"tag,omitempty"`
}
func (x *PrincipleTargetInfo) Reset() {
*x = PrincipleTargetInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_command_command_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PrincipleTargetInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PrincipleTargetInfo) ProtoMessage() {}
func (x *PrincipleTargetInfo) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PrincipleTargetInfo.ProtoReflect.Descriptor instead.
func (*PrincipleTargetInfo) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{3}
}
func (x *PrincipleTargetInfo) GetTag() []string {
if x != nil {
return x.Tag
}
return nil
}
type OverrideInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
}
func (x *OverrideInfo) Reset() {
*x = OverrideInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_command_command_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *OverrideInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*OverrideInfo) ProtoMessage() {}
func (x *OverrideInfo) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use OverrideInfo.ProtoReflect.Descriptor instead.
func (*OverrideInfo) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{4}
}
func (x *OverrideInfo) GetTarget() string {
if x != nil {
return x.Target
}
return ""
}
type BalancerMsg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Override *OverrideInfo `protobuf:"bytes,5,opt,name=override,proto3" json:"override,omitempty"`
PrincipleTarget *PrincipleTargetInfo `protobuf:"bytes,6,opt,name=principle_target,json=principleTarget,proto3" json:"principle_target,omitempty"`
}
func (x *BalancerMsg) Reset() {
*x = BalancerMsg{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_command_command_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *BalancerMsg) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BalancerMsg) ProtoMessage() {}
func (x *BalancerMsg) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use BalancerMsg.ProtoReflect.Descriptor instead.
func (*BalancerMsg) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{5}
}
func (x *BalancerMsg) GetOverride() *OverrideInfo {
if x != nil {
return x.Override
}
return nil
}
func (x *BalancerMsg) GetPrincipleTarget() *PrincipleTargetInfo {
if x != nil {
return x.PrincipleTarget
}
return nil
}
type GetBalancerInfoRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
}
func (x *GetBalancerInfoRequest) Reset() {
*x = GetBalancerInfoRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_command_command_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetBalancerInfoRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetBalancerInfoRequest) ProtoMessage() {}
func (x *GetBalancerInfoRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetBalancerInfoRequest.ProtoReflect.Descriptor instead.
func (*GetBalancerInfoRequest) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{6}
}
func (x *GetBalancerInfoRequest) GetTag() string {
if x != nil {
return x.Tag
}
return ""
}
type GetBalancerInfoResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Balancer *BalancerMsg `protobuf:"bytes,1,opt,name=balancer,proto3" json:"balancer,omitempty"`
}
func (x *GetBalancerInfoResponse) Reset() {
*x = GetBalancerInfoResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_command_command_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetBalancerInfoResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetBalancerInfoResponse) ProtoMessage() {}
func (x *GetBalancerInfoResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetBalancerInfoResponse.ProtoReflect.Descriptor instead.
func (*GetBalancerInfoResponse) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{7}
}
func (x *GetBalancerInfoResponse) GetBalancer() *BalancerMsg {
if x != nil {
return x.Balancer
}
return nil
}
type OverrideBalancerTargetRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
BalancerTag string `protobuf:"bytes,1,opt,name=balancerTag,proto3" json:"balancerTag,omitempty"`
Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
}
func (x *OverrideBalancerTargetRequest) Reset() {
*x = OverrideBalancerTargetRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_command_command_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *OverrideBalancerTargetRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*OverrideBalancerTargetRequest) ProtoMessage() {}
func (x *OverrideBalancerTargetRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use OverrideBalancerTargetRequest.ProtoReflect.Descriptor instead.
func (*OverrideBalancerTargetRequest) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{8}
}
func (x *OverrideBalancerTargetRequest) GetBalancerTag() string {
if x != nil {
return x.BalancerTag
}
return ""
}
func (x *OverrideBalancerTargetRequest) GetTarget() string {
if x != nil {
return x.Target
}
return ""
}
type OverrideBalancerTargetResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *OverrideBalancerTargetResponse) Reset() {
*x = OverrideBalancerTargetResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_command_command_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *OverrideBalancerTargetResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*OverrideBalancerTargetResponse) ProtoMessage() {}
func (x *OverrideBalancerTargetResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use OverrideBalancerTargetResponse.ProtoReflect.Descriptor instead.
func (*OverrideBalancerTargetResponse) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{9}
}
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -303,7 +639,7 @@ type Config struct {
func (x *Config) Reset() {
*x = Config{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_command_command_proto_msgTypes[3]
mi := &file_app_router_command_command_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -316,7 +652,7 @@ func (x *Config) String() string {
func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[3]
mi := &file_app_router_command_command_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -329,7 +665,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{3}
return file_app_router_command_command_proto_rawDescGZIP(), []int{10}
}
var File_app_router_command_command_proto protoreflect.FileDescriptor
@@ -390,29 +726,78 @@ var file_app_router_command_command_proto_rawDesc = []byte{
0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x75,
0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
0x08, 0x52, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xf0, 0x01, 0x0a, 0x0e, 0x52,
0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7b, 0x0a,
0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e,
0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x35, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x22, 0x27, 0x0a, 0x13, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01,
0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x26, 0x0a, 0x0c, 0x4f, 0x76, 0x65,
0x72, 0x72, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x22, 0xa9, 0x01, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73,
0x67, 0x12, 0x41, 0x0a, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76,
0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6f, 0x76, 0x65, 0x72,
0x72, 0x69, 0x64, 0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c,
0x65, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70,
0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x70, 0x72,
0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2a, 0x0a,
0x16, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x5b, 0x0a, 0x17, 0x47, 0x65, 0x74,
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e,
0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e,
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43,
0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65,
0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75,
0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x42, 0x67, 0x0a,
0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2c,
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, 0x72, 0x6f,
0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58,
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x08, 0x62, 0x61,
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x1d, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e,
0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x61,
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x22, 0x20, 0x0a, 0x1e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c,
0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xf6, 0x03,
0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x12, 0x7b, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75,
0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x35, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75,
0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69,
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x61, 0x0a,
0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00,
0x12, 0x76, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49,
0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65,
0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47,
0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x8b, 0x01, 0x0a, 0x16, 0x4f, 0x76, 0x65,
0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x12, 0x36, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76,
0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61,
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2c, 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, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70,
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -427,28 +812,42 @@ func file_app_router_command_command_proto_rawDescGZIP() []byte {
return file_app_router_command_command_proto_rawDescData
}
var file_app_router_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_app_router_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_app_router_command_command_proto_goTypes = []interface{}{
(*RoutingContext)(nil), // 0: xray.app.router.command.RoutingContext
(*SubscribeRoutingStatsRequest)(nil), // 1: xray.app.router.command.SubscribeRoutingStatsRequest
(*TestRouteRequest)(nil), // 2: xray.app.router.command.TestRouteRequest
(*Config)(nil), // 3: xray.app.router.command.Config
nil, // 4: xray.app.router.command.RoutingContext.AttributesEntry
(net.Network)(0), // 5: xray.common.net.Network
(*PrincipleTargetInfo)(nil), // 3: xray.app.router.command.PrincipleTargetInfo
(*OverrideInfo)(nil), // 4: xray.app.router.command.OverrideInfo
(*BalancerMsg)(nil), // 5: xray.app.router.command.BalancerMsg
(*GetBalancerInfoRequest)(nil), // 6: xray.app.router.command.GetBalancerInfoRequest
(*GetBalancerInfoResponse)(nil), // 7: xray.app.router.command.GetBalancerInfoResponse
(*OverrideBalancerTargetRequest)(nil), // 8: xray.app.router.command.OverrideBalancerTargetRequest
(*OverrideBalancerTargetResponse)(nil), // 9: xray.app.router.command.OverrideBalancerTargetResponse
(*Config)(nil), // 10: xray.app.router.command.Config
nil, // 11: xray.app.router.command.RoutingContext.AttributesEntry
(net.Network)(0), // 12: xray.common.net.Network
}
var file_app_router_command_command_proto_depIdxs = []int32{
5, // 0: xray.app.router.command.RoutingContext.Network:type_name -> xray.common.net.Network
4, // 1: xray.app.router.command.RoutingContext.Attributes:type_name -> xray.app.router.command.RoutingContext.AttributesEntry
12, // 0: xray.app.router.command.RoutingContext.Network:type_name -> xray.common.net.Network
11, // 1: xray.app.router.command.RoutingContext.Attributes:type_name -> xray.app.router.command.RoutingContext.AttributesEntry
0, // 2: xray.app.router.command.TestRouteRequest.RoutingContext:type_name -> xray.app.router.command.RoutingContext
1, // 3: xray.app.router.command.RoutingService.SubscribeRoutingStats:input_type -> xray.app.router.command.SubscribeRoutingStatsRequest
2, // 4: xray.app.router.command.RoutingService.TestRoute:input_type -> xray.app.router.command.TestRouteRequest
0, // 5: xray.app.router.command.RoutingService.SubscribeRoutingStats:output_type -> xray.app.router.command.RoutingContext
0, // 6: xray.app.router.command.RoutingService.TestRoute:output_type -> xray.app.router.command.RoutingContext
5, // [5:7] is the sub-list for method output_type
3, // [3:5] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
4, // 3: xray.app.router.command.BalancerMsg.override:type_name -> xray.app.router.command.OverrideInfo
3, // 4: xray.app.router.command.BalancerMsg.principle_target:type_name -> xray.app.router.command.PrincipleTargetInfo
5, // 5: xray.app.router.command.GetBalancerInfoResponse.balancer:type_name -> xray.app.router.command.BalancerMsg
1, // 6: xray.app.router.command.RoutingService.SubscribeRoutingStats:input_type -> xray.app.router.command.SubscribeRoutingStatsRequest
2, // 7: xray.app.router.command.RoutingService.TestRoute:input_type -> xray.app.router.command.TestRouteRequest
6, // 8: xray.app.router.command.RoutingService.GetBalancerInfo:input_type -> xray.app.router.command.GetBalancerInfoRequest
8, // 9: xray.app.router.command.RoutingService.OverrideBalancerTarget:input_type -> xray.app.router.command.OverrideBalancerTargetRequest
0, // 10: xray.app.router.command.RoutingService.SubscribeRoutingStats:output_type -> xray.app.router.command.RoutingContext
0, // 11: xray.app.router.command.RoutingService.TestRoute:output_type -> xray.app.router.command.RoutingContext
7, // 12: xray.app.router.command.RoutingService.GetBalancerInfo:output_type -> xray.app.router.command.GetBalancerInfoResponse
9, // 13: xray.app.router.command.RoutingService.OverrideBalancerTarget:output_type -> xray.app.router.command.OverrideBalancerTargetResponse
10, // [10:14] is the sub-list for method output_type
6, // [6:10] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_app_router_command_command_proto_init() }
@@ -494,6 +893,90 @@ func file_app_router_command_command_proto_init() {
}
}
file_app_router_command_command_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PrincipleTargetInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OverrideInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BalancerMsg); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetBalancerInfoRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetBalancerInfoResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OverrideBalancerTargetRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OverrideBalancerTargetResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
@@ -512,7 +995,7 @@ func file_app_router_command_command_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_router_command_command_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumMessages: 12,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -60,10 +60,41 @@ message TestRouteRequest {
bool PublishResult = 3;
}
message PrincipleTargetInfo {
repeated string tag = 1;
}
message OverrideInfo {
string target = 2;
}
message BalancerMsg {
OverrideInfo override = 5;
PrincipleTargetInfo principle_target = 6;
}
message GetBalancerInfoRequest {
string tag = 1;
}
message GetBalancerInfoResponse {
BalancerMsg balancer = 1;
}
message OverrideBalancerTargetRequest {
string balancerTag = 1;
string target = 2;
}
message OverrideBalancerTargetResponse {}
service RoutingService {
rpc SubscribeRoutingStats(SubscribeRoutingStatsRequest)
returns (stream RoutingContext) {}
rpc TestRoute(TestRouteRequest) returns (RoutingContext) {}
rpc GetBalancerInfo(GetBalancerInfoRequest) returns (GetBalancerInfoResponse){}
rpc OverrideBalancerTarget(OverrideBalancerTargetRequest) returns (OverrideBalancerTargetResponse) {}
}
message Config {}

View File

@@ -21,6 +21,8 @@ const _ = grpc.SupportPackageIsVersion7
const (
RoutingService_SubscribeRoutingStats_FullMethodName = "/xray.app.router.command.RoutingService/SubscribeRoutingStats"
RoutingService_TestRoute_FullMethodName = "/xray.app.router.command.RoutingService/TestRoute"
RoutingService_GetBalancerInfo_FullMethodName = "/xray.app.router.command.RoutingService/GetBalancerInfo"
RoutingService_OverrideBalancerTarget_FullMethodName = "/xray.app.router.command.RoutingService/OverrideBalancerTarget"
)
// RoutingServiceClient is the client API for RoutingService service.
@@ -29,6 +31,8 @@ const (
type RoutingServiceClient interface {
SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (RoutingService_SubscribeRoutingStatsClient, error)
TestRoute(ctx context.Context, in *TestRouteRequest, opts ...grpc.CallOption) (*RoutingContext, error)
GetBalancerInfo(ctx context.Context, in *GetBalancerInfoRequest, opts ...grpc.CallOption) (*GetBalancerInfoResponse, error)
OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error)
}
type routingServiceClient struct {
@@ -80,12 +84,32 @@ func (c *routingServiceClient) TestRoute(ctx context.Context, in *TestRouteReque
return out, nil
}
func (c *routingServiceClient) GetBalancerInfo(ctx context.Context, in *GetBalancerInfoRequest, opts ...grpc.CallOption) (*GetBalancerInfoResponse, error) {
out := new(GetBalancerInfoResponse)
err := c.cc.Invoke(ctx, RoutingService_GetBalancerInfo_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *routingServiceClient) OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error) {
out := new(OverrideBalancerTargetResponse)
err := c.cc.Invoke(ctx, RoutingService_OverrideBalancerTarget_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// RoutingServiceServer is the server API for RoutingService service.
// All implementations must embed UnimplementedRoutingServiceServer
// for forward compatibility
type RoutingServiceServer interface {
SubscribeRoutingStats(*SubscribeRoutingStatsRequest, RoutingService_SubscribeRoutingStatsServer) error
TestRoute(context.Context, *TestRouteRequest) (*RoutingContext, error)
GetBalancerInfo(context.Context, *GetBalancerInfoRequest) (*GetBalancerInfoResponse, error)
OverrideBalancerTarget(context.Context, *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error)
mustEmbedUnimplementedRoutingServiceServer()
}
@@ -99,6 +123,12 @@ func (UnimplementedRoutingServiceServer) SubscribeRoutingStats(*SubscribeRouting
func (UnimplementedRoutingServiceServer) TestRoute(context.Context, *TestRouteRequest) (*RoutingContext, error) {
return nil, status.Errorf(codes.Unimplemented, "method TestRoute not implemented")
}
func (UnimplementedRoutingServiceServer) GetBalancerInfo(context.Context, *GetBalancerInfoRequest) (*GetBalancerInfoResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBalancerInfo not implemented")
}
func (UnimplementedRoutingServiceServer) OverrideBalancerTarget(context.Context, *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method OverrideBalancerTarget not implemented")
}
func (UnimplementedRoutingServiceServer) mustEmbedUnimplementedRoutingServiceServer() {}
// UnsafeRoutingServiceServer may be embedded to opt out of forward compatibility for this service.
@@ -151,6 +181,42 @@ func _RoutingService_TestRoute_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _RoutingService_GetBalancerInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetBalancerInfoRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RoutingServiceServer).GetBalancerInfo(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RoutingService_GetBalancerInfo_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RoutingServiceServer).GetBalancerInfo(ctx, req.(*GetBalancerInfoRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RoutingService_OverrideBalancerTarget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(OverrideBalancerTargetRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RoutingServiceServer).OverrideBalancerTarget(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RoutingService_OverrideBalancerTarget_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RoutingServiceServer).OverrideBalancerTarget(ctx, req.(*OverrideBalancerTargetRequest))
}
return interceptor(ctx, in, info, handler)
}
// RoutingService_ServiceDesc is the grpc.ServiceDesc for RoutingService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -162,6 +228,14 @@ var RoutingService_ServiceDesc = grpc.ServiceDesc{
MethodName: "TestRoute",
Handler: _RoutingService_TestRoute_Handler,
},
{
MethodName: "GetBalancerInfo",
Handler: _RoutingService_GetBalancerInfo_Handler,
},
{
MethodName: "OverrideBalancerTarget",
Handler: _RoutingService_OverrideBalancerTarget_Handler,
},
},
Streams: []grpc.StreamDesc{
{

View File

@@ -318,7 +318,7 @@ func TestSerivceTestRoute(t *testing.T) {
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
},
},
}, mocks.NewDNSClient(mockCtl), mocks.NewOutboundManager(mockCtl)))
}, mocks.NewDNSClient(mockCtl), mocks.NewOutboundManager(mockCtl), nil))
lis := bufconn.Listen(1024 * 1024)
bufDialer := func(context.Context, string) (net.Conn, error) {

View File

@@ -121,22 +121,45 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
return conds, nil
}
func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) {
switch br.Strategy {
case "leastPing":
// Build builds the balancing rule
func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatcher) (*Balancer, error) {
switch strings.ToLower(br.Strategy) {
case "leastping":
return &Balancer{
selectors: br.OutboundSelector,
strategy: &LeastPingStrategy{},
ohm: ohm,
}, nil
case "random":
fallthrough
default:
case "roundrobin":
return &Balancer{
selectors: br.OutboundSelector,
strategy: &RandomStrategy{},
strategy: &RoundRobinStrategy{},
ohm: ohm,
}, nil
case "leastload":
i, err := br.StrategySettings.GetInstance()
if err != nil {
return nil, err
}
s, ok := i.(*StrategyLeastLoadConfig)
if !ok {
return nil, newError("not a StrategyLeastLoadConfig").AtError()
}
leastLoadStrategy := NewLeastLoadStrategy(s)
return &Balancer{
selectors: br.OutboundSelector,
ohm: ohm, fallbackTag: br.FallbackTag,
strategy: leastLoadStrategy,
}, nil
case "random":
fallthrough
case "":
return &Balancer{
selectors: br.OutboundSelector,
ohm: ohm, fallbackTag: br.FallbackTag,
strategy: &RandomStrategy{},
}, nil
default:
return nil, newError("unrecognized balancer type")
}
}

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/router/config.proto
@@ -8,6 +8,7 @@ package router
import (
net "github.com/xtls/xray-core/common/net"
serial "github.com/xtls/xray-core/common/serial"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@@ -131,7 +132,7 @@ func (x Config_DomainStrategy) Number() protoreflect.EnumNumber {
// Deprecated: Use Config_DomainStrategy.Descriptor instead.
func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) {
return file_app_router_config_proto_rawDescGZIP(), []int{8, 0}
return file_app_router_config_proto_rawDescGZIP(), []int{10, 0}
}
// Domain for routing decision.
@@ -710,6 +711,8 @@ type BalancingRule struct {
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
OutboundSelector []string `protobuf:"bytes,2,rep,name=outbound_selector,json=outboundSelector,proto3" json:"outbound_selector,omitempty"`
Strategy string `protobuf:"bytes,3,opt,name=strategy,proto3" json:"strategy,omitempty"`
StrategySettings *serial.TypedMessage `protobuf:"bytes,4,opt,name=strategy_settings,json=strategySettings,proto3" json:"strategy_settings,omitempty"`
FallbackTag string `protobuf:"bytes,5,opt,name=fallback_tag,json=fallbackTag,proto3" json:"fallback_tag,omitempty"`
}
func (x *BalancingRule) Reset() {
@@ -765,6 +768,167 @@ func (x *BalancingRule) GetStrategy() string {
return ""
}
func (x *BalancingRule) GetStrategySettings() *serial.TypedMessage {
if x != nil {
return x.StrategySettings
}
return nil
}
func (x *BalancingRule) GetFallbackTag() string {
if x != nil {
return x.FallbackTag
}
return ""
}
type StrategyWeight struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Regexp bool `protobuf:"varint,1,opt,name=regexp,proto3" json:"regexp,omitempty"`
Match string `protobuf:"bytes,2,opt,name=match,proto3" json:"match,omitempty"`
Value float32 `protobuf:"fixed32,3,opt,name=value,proto3" json:"value,omitempty"`
}
func (x *StrategyWeight) Reset() {
*x = StrategyWeight{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_config_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *StrategyWeight) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StrategyWeight) ProtoMessage() {}
func (x *StrategyWeight) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StrategyWeight.ProtoReflect.Descriptor instead.
func (*StrategyWeight) Descriptor() ([]byte, []int) {
return file_app_router_config_proto_rawDescGZIP(), []int{8}
}
func (x *StrategyWeight) GetRegexp() bool {
if x != nil {
return x.Regexp
}
return false
}
func (x *StrategyWeight) GetMatch() string {
if x != nil {
return x.Match
}
return ""
}
func (x *StrategyWeight) GetValue() float32 {
if x != nil {
return x.Value
}
return 0
}
type StrategyLeastLoadConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// weight settings
Costs []*StrategyWeight `protobuf:"bytes,2,rep,name=costs,proto3" json:"costs,omitempty"`
// RTT baselines for selecting, int64 values of time.Duration
Baselines []int64 `protobuf:"varint,3,rep,packed,name=baselines,proto3" json:"baselines,omitempty"`
// expected nodes count to select
Expected int32 `protobuf:"varint,4,opt,name=expected,proto3" json:"expected,omitempty"`
// max acceptable rtt, filter away high delay nodes. defalut 0
MaxRTT int64 `protobuf:"varint,5,opt,name=maxRTT,proto3" json:"maxRTT,omitempty"`
// acceptable failure rate
Tolerance float32 `protobuf:"fixed32,6,opt,name=tolerance,proto3" json:"tolerance,omitempty"`
}
func (x *StrategyLeastLoadConfig) Reset() {
*x = StrategyLeastLoadConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_config_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *StrategyLeastLoadConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StrategyLeastLoadConfig) ProtoMessage() {}
func (x *StrategyLeastLoadConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StrategyLeastLoadConfig.ProtoReflect.Descriptor instead.
func (*StrategyLeastLoadConfig) Descriptor() ([]byte, []int) {
return file_app_router_config_proto_rawDescGZIP(), []int{9}
}
func (x *StrategyLeastLoadConfig) GetCosts() []*StrategyWeight {
if x != nil {
return x.Costs
}
return nil
}
func (x *StrategyLeastLoadConfig) GetBaselines() []int64 {
if x != nil {
return x.Baselines
}
return nil
}
func (x *StrategyLeastLoadConfig) GetExpected() int32 {
if x != nil {
return x.Expected
}
return 0
}
func (x *StrategyLeastLoadConfig) GetMaxRTT() int64 {
if x != nil {
return x.MaxRTT
}
return 0
}
func (x *StrategyLeastLoadConfig) GetTolerance() float32 {
if x != nil {
return x.Tolerance
}
return 0
}
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -778,7 +942,7 @@ type Config struct {
func (x *Config) Reset() {
*x = Config{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_config_proto_msgTypes[8]
mi := &file_app_router_config_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -791,7 +955,7 @@ func (x *Config) String() string {
func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[8]
mi := &file_app_router_config_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -804,7 +968,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_app_router_config_proto_rawDescGZIP(), []int{8}
return file_app_router_config_proto_rawDescGZIP(), []int{10}
}
func (x *Config) GetDomainStrategy() Config_DomainStrategy {
@@ -844,7 +1008,7 @@ type Domain_Attribute struct {
func (x *Domain_Attribute) Reset() {
*x = Domain_Attribute{}
if protoimpl.UnsafeEnabled {
mi := &file_app_router_config_proto_msgTypes[9]
mi := &file_app_router_config_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -857,7 +1021,7 @@ func (x *Domain_Attribute) String() string {
func (*Domain_Attribute) ProtoMessage() {}
func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[9]
mi := &file_app_router_config_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -922,142 +1086,169 @@ var File_app_router_config_proto protoreflect.FileDescriptor
var file_app_router_config_proto_rawDesc = []byte{
0x0a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x1a, 0x15, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x6e, 0x65,
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb3, 0x02, 0x0a, 0x06,
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x79,
0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f,
0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69,
0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x1a,
0x6c, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03,
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1f,
0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0d,
0x0a, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x32, 0x0a,
0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x10, 0x00,
0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10,
0x03, 0x22, 0x2e, 0x0a, 0x04, 0x43, 0x49, 0x44, 0x52, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65,
0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69,
0x78, 0x22, 0x7a, 0x0a, 0x05, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x29, 0x0a,
0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49,
0x44, 0x52, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x65,
0x72, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0c, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x39, 0x0a,
0x09, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x65, 0x6e,
0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49,
0x50, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x5d, 0x0a, 0x07, 0x47, 0x65, 0x6f, 0x53,
0x69, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63,
0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x3d, 0x0a, 0x0b, 0x47, 0x65, 0x6f, 0x53, 0x69,
0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52,
0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xa2, 0x07, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x69,
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x0d, 0x62, 0x61,
0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28,
0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x54, 0x61,
0x67, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61,
0x69, 0x6e, 0x12, 0x2d, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x63, 0x69, 0x64,
0x72, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12,
0x3d, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42,
0x02, 0x18, 0x01, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x36,
0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f,
0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
0x6b, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b,
0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x08, 0x6e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x18, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e,
0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x69, 0x64, 0x72,
0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52, 0x42, 0x02, 0x18,
0x01, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x69, 0x64, 0x72, 0x12, 0x39, 0x0a,
0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20,
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb3,
0x02, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x12, 0x3f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x41, 0x74,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
0x74, 0x65, 0x1a, 0x6c, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12,
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x79, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x22, 0x32, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x6c, 0x61, 0x69,
0x6e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x01, 0x12, 0x0a,
0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75,
0x6c, 0x6c, 0x10, 0x03, 0x22, 0x2e, 0x0a, 0x04, 0x43, 0x49, 0x44, 0x52, 0x12, 0x0e, 0x0a, 0x02,
0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x16, 0x0a, 0x06,
0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72,
0x65, 0x66, 0x69, 0x78, 0x22, 0x7a, 0x0a, 0x05, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x12, 0x21, 0x0a,
0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65,
0x12, 0x29, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
0x2e, 0x43, 0x49, 0x44, 0x52, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x72,
0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01,
0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68,
0x22, 0x39, 0x0a, 0x09, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x0a,
0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47,
0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x5d, 0x0a, 0x07, 0x47,
0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72,
0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d,
0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61,
0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x3d, 0x0a, 0x0b, 0x47, 0x65,
0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74,
0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69,
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xa2, 0x07, 0x0a, 0x0b, 0x52, 0x6f,
0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a,
0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c,
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e,
0x67, 0x54, 0x61, 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2d, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x03, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04,
0x63, 0x69, 0x64, 0x72, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0a, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x43, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x0a,
0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28,
0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x0a, 0x0b,
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28,
0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a,
0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52,
0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x4c, 0x0a, 0x0a, 0x61, 0x74, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e,
0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72,
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69,
0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x1a, 0x3d,
0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a,
0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0x6a, 0x0a, 0x0d, 0x42,
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03,
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b,
0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73,
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72,
0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52,
0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e,
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62,
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e,
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08,
0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49,
0x70, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61,
0x74, 0x63, 0x68, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d,
0x61, 0x6e, 0x64, 0x10, 0x03, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24,
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, 0x72, 0x6f,
0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e,
0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f,
0x69, 0x70, 0x12, 0x3d, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e,
0x67, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67,
0x65, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52,
0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0c, 0x6e, 0x65, 0x74,
0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x02, 0x18,
0x01, 0x52, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x34,
0x0a, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0e,
0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e,
0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77,
0x6f, 0x72, 0x6b, 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63,
0x69, 0x64, 0x72, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52,
0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x69, 0x64, 0x72,
0x12, 0x39, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70,
0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x43, 0x0a, 0x10, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74,
0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74,
0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07,
0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12,
0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08,
0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67,
0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03,
0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x4c, 0x0a, 0x0a,
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x2c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x41,
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a,
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f,
0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65,
0x72, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc,
0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65,
0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f,
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12,
0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73,
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65,
0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a,
0x0e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12,
0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x35, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52,
0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69,
0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c,
0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65,
0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c,
0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61,
0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04,
0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e,
0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42,
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61,
0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a,
0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70,
0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74,
0x63, 0x68, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61,
0x6e, 0x64, 0x10, 0x03, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 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, 0x72, 0x6f, 0x75,
0x74, 0x65, 0x72, 0xaa, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -1073,7 +1264,7 @@ func file_app_router_config_proto_rawDescGZIP() []byte {
}
var file_app_router_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_app_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_app_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_app_router_config_proto_goTypes = []interface{}{
(Domain_Type)(0), // 0: xray.app.router.Domain.Type
(Config_DomainStrategy)(0), // 1: xray.app.router.Config.DomainStrategy
@@ -1085,17 +1276,20 @@ var file_app_router_config_proto_goTypes = []interface{}{
(*GeoSiteList)(nil), // 7: xray.app.router.GeoSiteList
(*RoutingRule)(nil), // 8: xray.app.router.RoutingRule
(*BalancingRule)(nil), // 9: xray.app.router.BalancingRule
(*Config)(nil), // 10: xray.app.router.Config
(*Domain_Attribute)(nil), // 11: xray.app.router.Domain.Attribute
nil, // 12: xray.app.router.RoutingRule.AttributesEntry
(*net.PortRange)(nil), // 13: xray.common.net.PortRange
(*net.PortList)(nil), // 14: xray.common.net.PortList
(*net.NetworkList)(nil), // 15: xray.common.net.NetworkList
(net.Network)(0), // 16: xray.common.net.Network
(*StrategyWeight)(nil), // 10: xray.app.router.StrategyWeight
(*StrategyLeastLoadConfig)(nil), // 11: xray.app.router.StrategyLeastLoadConfig
(*Config)(nil), // 12: xray.app.router.Config
(*Domain_Attribute)(nil), // 13: xray.app.router.Domain.Attribute
nil, // 14: xray.app.router.RoutingRule.AttributesEntry
(*net.PortRange)(nil), // 15: xray.common.net.PortRange
(*net.PortList)(nil), // 16: xray.common.net.PortList
(*net.NetworkList)(nil), // 17: xray.common.net.NetworkList
(net.Network)(0), // 18: xray.common.net.Network
(*serial.TypedMessage)(nil), // 19: xray.common.serial.TypedMessage
}
var file_app_router_config_proto_depIdxs = []int32{
0, // 0: xray.app.router.Domain.type:type_name -> xray.app.router.Domain.Type
11, // 1: xray.app.router.Domain.attribute:type_name -> xray.app.router.Domain.Attribute
13, // 1: xray.app.router.Domain.attribute:type_name -> xray.app.router.Domain.Attribute
3, // 2: xray.app.router.GeoIP.cidr:type_name -> xray.app.router.CIDR
4, // 3: xray.app.router.GeoIPList.entry:type_name -> xray.app.router.GeoIP
2, // 4: xray.app.router.GeoSite.domain:type_name -> xray.app.router.Domain
@@ -1103,22 +1297,24 @@ var file_app_router_config_proto_depIdxs = []int32{
2, // 6: xray.app.router.RoutingRule.domain:type_name -> xray.app.router.Domain
3, // 7: xray.app.router.RoutingRule.cidr:type_name -> xray.app.router.CIDR
4, // 8: xray.app.router.RoutingRule.geoip:type_name -> xray.app.router.GeoIP
13, // 9: xray.app.router.RoutingRule.port_range:type_name -> xray.common.net.PortRange
14, // 10: xray.app.router.RoutingRule.port_list:type_name -> xray.common.net.PortList
15, // 11: xray.app.router.RoutingRule.network_list:type_name -> xray.common.net.NetworkList
16, // 12: xray.app.router.RoutingRule.networks:type_name -> xray.common.net.Network
15, // 9: xray.app.router.RoutingRule.port_range:type_name -> xray.common.net.PortRange
16, // 10: xray.app.router.RoutingRule.port_list:type_name -> xray.common.net.PortList
17, // 11: xray.app.router.RoutingRule.network_list:type_name -> xray.common.net.NetworkList
18, // 12: xray.app.router.RoutingRule.networks:type_name -> xray.common.net.Network
3, // 13: xray.app.router.RoutingRule.source_cidr:type_name -> xray.app.router.CIDR
4, // 14: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
14, // 15: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
12, // 16: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
1, // 17: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
8, // 18: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
9, // 19: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
20, // [20:20] is the sub-list for method output_type
20, // [20:20] is the sub-list for method input_type
20, // [20:20] is the sub-list for extension type_name
20, // [20:20] is the sub-list for extension extendee
0, // [0:20] is the sub-list for field type_name
16, // 15: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
14, // 16: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
19, // 17: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
10, // 18: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
1, // 19: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
8, // 20: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
9, // 21: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
22, // [22:22] is the sub-list for method output_type
22, // [22:22] is the sub-list for method input_type
22, // [22:22] is the sub-list for extension type_name
22, // [22:22] is the sub-list for extension extendee
0, // [0:22] is the sub-list for field type_name
}
func init() { file_app_router_config_proto_init() }
@@ -1224,7 +1420,7 @@ func file_app_router_config_proto_init() {
}
}
file_app_router_config_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
switch v := v.(*StrategyWeight); i {
case 0:
return &v.state
case 1:
@@ -1236,6 +1432,30 @@ func file_app_router_config_proto_init() {
}
}
file_app_router_config_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StrategyLeastLoadConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
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_router_config_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Domain_Attribute); i {
case 0:
return &v.state
@@ -1252,7 +1472,7 @@ func file_app_router_config_proto_init() {
(*RoutingRule_Tag)(nil),
(*RoutingRule_BalancingTag)(nil),
}
file_app_router_config_proto_msgTypes[9].OneofWrappers = []interface{}{
file_app_router_config_proto_msgTypes[11].OneofWrappers = []interface{}{
(*Domain_Attribute_BoolValue)(nil),
(*Domain_Attribute_IntValue)(nil),
}
@@ -1262,7 +1482,7 @@ func file_app_router_config_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_router_config_proto_rawDesc,
NumEnums: 2,
NumMessages: 11,
NumMessages: 13,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -6,6 +6,7 @@ option go_package = "github.com/xtls/xray-core/app/router";
option java_package = "com.xray.app.router";
option java_multiple_files = true;
import "common/serial/typed_message.proto";
import "common/net/port.proto";
import "common/net/network.proto";
@@ -128,6 +129,27 @@ message BalancingRule {
string tag = 1;
repeated string outbound_selector = 2;
string strategy = 3;
xray.common.serial.TypedMessage strategy_settings = 4;
string fallback_tag = 5;
}
message StrategyWeight {
bool regexp = 1;
string match = 2;
float value =3;
}
message StrategyLeastLoadConfig {
// weight settings
repeated StrategyWeight costs = 2;
// RTT baselines for selecting, int64 values of time.Duration
repeated int64 baselines = 3;
// expected nodes count to select
int32 expected = 4;
// max acceptable rtt, filter away high delay nodes. defalut 0
int64 maxRTT = 5;
// acceptable failure rate
float tolerance = 6;
}
message Config {

View File

@@ -29,13 +29,13 @@ type Route struct {
}
// Init initializes the Router.
func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm outbound.Manager) error {
func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm outbound.Manager, dispatcher routing.Dispatcher) error {
r.domainStrategy = config.DomainStrategy
r.dns = d
r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
for _, rule := range config.BalancingRule {
balancer, err := rule.Build(ohm)
balancer, err := rule.Build(ohm, dispatcher)
if err != nil {
return err
}
@@ -113,12 +113,12 @@ func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context,
}
// Start implements common.Runnable.
func (*Router) Start() error {
func (r *Router) Start() error {
return nil
}
// Close implements common.Closable.
func (*Router) Close() error {
func (r *Router) Close() error {
return nil
}
@@ -140,8 +140,8 @@ func (r *Route) GetOutboundTag() string {
func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
r := new(Router)
if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager) error {
return r.Init(ctx, config.(*Config), d, ohm)
if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager, dispatcher routing.Dispatcher) error {
return r.Init(ctx, config.(*Config), d, ohm, dispatcher)
}); err != nil {
return nil, err
}

View File

@@ -43,7 +43,7 @@ func TestSimpleRouter(t *testing.T) {
common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
Manager: mockOhm,
HandlerSelector: mockHs,
}))
}, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
@@ -84,7 +84,7 @@ func TestSimpleBalancer(t *testing.T) {
common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
Manager: mockOhm,
HandlerSelector: mockHs,
}))
}, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
@@ -94,6 +94,55 @@ func TestSimpleBalancer(t *testing.T) {
}
}
/*
Do not work right now: need a full client setup
func TestLeastLoadBalancer(t *testing.T) {
config := &Config{
Rule: []*RoutingRule{
{
TargetTag: &RoutingRule_BalancingTag{
BalancingTag: "balance",
},
Networks: []net.Network{net.Network_TCP},
},
},
BalancingRule: []*BalancingRule{
{
Tag: "balance",
OutboundSelector: []string{"test-"},
Strategy: "leastLoad",
StrategySettings: serial.ToTypedMessage(&StrategyLeastLoadConfig{
Baselines: nil,
Expected: 1,
}),
},
},
}
mockCtl := gomock.NewController(t)
defer mockCtl.Finish()
mockDNS := mocks.NewDNSClient(mockCtl)
mockOhm := mocks.NewOutboundManager(mockCtl)
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test1"})
r := new(Router)
common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
Manager: mockOhm,
HandlerSelector: mockHs,
}, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
common.Must(err)
if tag := route.GetOutboundTag(); tag != "test1" {
t.Error("expect tag 'test1', bug actually ", tag)
}
}*/
func TestIPOnDemand(t *testing.T) {
config := &Config{
DomainStrategy: Config_IpOnDemand,
@@ -123,7 +172,7 @@ func TestIPOnDemand(t *testing.T) {
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
r := new(Router)
common.Must(r.Init(context.TODO(), config, mockDNS, nil))
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
@@ -162,7 +211,7 @@ func TestIPIfNonMatchDomain(t *testing.T) {
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
r := new(Router)
common.Must(r.Init(context.TODO(), config, mockDNS, nil))
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
@@ -196,7 +245,7 @@ func TestIPIfNonMatchIP(t *testing.T) {
mockDNS := mocks.NewDNSClient(mockCtl)
r := new(Router)
common.Must(r.Init(context.TODO(), config, mockDNS, nil))
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.LocalHostIP, 80)})
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))

View File

@@ -0,0 +1,200 @@
package router
import (
"context"
"math"
"sort"
"time"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension"
)
// LeastLoadStrategy represents a least load balancing strategy
type LeastLoadStrategy struct {
settings *StrategyLeastLoadConfig
costs *WeightManager
observer extension.Observatory
ctx context.Context
}
func (l *LeastLoadStrategy) GetPrincipleTarget(strings []string) []string {
var ret []string
nodes := l.pickOutbounds(strings)
for _, v := range nodes {
ret = append(ret, v.Tag)
}
return ret
}
// NewLeastLoadStrategy creates a new LeastLoadStrategy with settings
func NewLeastLoadStrategy(settings *StrategyLeastLoadConfig) *LeastLoadStrategy {
return &LeastLoadStrategy{
settings: settings,
costs: NewWeightManager(
settings.Costs, 1,
func(value, cost float64) float64 {
return value * math.Pow(cost, 0.5)
},
),
}
}
// node is a minimal copy of HealthCheckResult
// we don't use HealthCheckResult directly because
// it may change by health checker during routing
type node struct {
Tag string
CountAll int
CountFail int
RTTAverage time.Duration
RTTDeviation time.Duration
RTTDeviationCost time.Duration
}
func (l *LeastLoadStrategy) InjectContext(ctx context.Context) {
l.ctx = ctx
}
func (s *LeastLoadStrategy) PickOutbound(candidates []string) string {
selects := s.pickOutbounds(candidates)
count := len(selects)
if count == 0 {
// goes to fallbackTag
return ""
}
return selects[dice.Roll(count)].Tag
}
func (s *LeastLoadStrategy) pickOutbounds(candidates []string) []*node {
qualified := s.getNodes(candidates, time.Duration(s.settings.MaxRTT))
selects := s.selectLeastLoad(qualified)
return selects
}
// selectLeastLoad selects nodes according to Baselines and Expected Count.
//
// The strategy always improves network response speed, not matter which mode below is configured.
// But they can still have different priorities.
//
// 1. Bandwidth priority: no Baseline + Expected Count > 0.: selects `Expected Count` of nodes.
// (one if Expected Count <= 0)
//
// 2. Bandwidth priority advanced: Baselines + Expected Count > 0.
// Select `Expected Count` amount of nodes, and also those near them according to baselines.
// In other words, it selects according to different Baselines, until one of them matches
// the Expected Count, if no Baseline matches, Expected Count applied.
//
// 3. Speed priority: Baselines + `Expected Count <= 0`.
// go through all baselines until find selects, if not, select none. Used in combination
// with 'balancer.fallbackTag', it means: selects qualified nodes or use the fallback.
func (s *LeastLoadStrategy) selectLeastLoad(nodes []*node) []*node {
if len(nodes) == 0 {
newError("least load: no qualified outbound").AtInfo().WriteToLog()
return nil
}
expected := int(s.settings.Expected)
availableCount := len(nodes)
if expected > availableCount {
return nodes
}
if expected <= 0 {
expected = 1
}
if len(s.settings.Baselines) == 0 {
return nodes[:expected]
}
count := 0
// go through all base line until find expected selects
for _, b := range s.settings.Baselines {
baseline := time.Duration(b)
for i := count; i < availableCount; i++ {
if nodes[i].RTTDeviationCost >= baseline {
break
}
count = i + 1
}
// don't continue if find expected selects
if count >= expected {
newError("applied baseline: ", baseline).AtDebug().WriteToLog()
break
}
}
if s.settings.Expected > 0 && count < expected {
count = expected
}
return nodes[:count]
}
func (s *LeastLoadStrategy) getNodes(candidates []string, maxRTT time.Duration) []*node {
if s.observer == nil {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observer = observatory
return nil
}))
}
observeResult, err := s.observer.GetObservation(s.ctx)
if err != nil {
newError("cannot get observation").Base(err).WriteToLog()
return make([]*node, 0)
}
results := observeResult.(*observatory.ObservationResult)
outboundlist := outboundList(candidates)
var ret []*node
for _, v := range results.Status {
if v.Alive && (v.Delay < maxRTT.Milliseconds() || maxRTT == 0) && outboundlist.contains(v.OutboundTag) {
record := &node{
Tag: v.OutboundTag,
CountAll: 1,
CountFail: 1,
RTTAverage: time.Duration(v.Delay) * time.Millisecond,
RTTDeviation: time.Duration(v.Delay) * time.Millisecond,
RTTDeviationCost: time.Duration(s.costs.Apply(v.OutboundTag, float64(time.Duration(v.Delay)*time.Millisecond))),
}
if v.HealthPing != nil {
record.RTTAverage = time.Duration(v.HealthPing.Average)
record.RTTDeviation = time.Duration(v.HealthPing.Deviation)
record.RTTDeviationCost = time.Duration(s.costs.Apply(v.OutboundTag, float64(v.HealthPing.Deviation)))
record.CountAll = int(v.HealthPing.All)
record.CountFail = int(v.HealthPing.Fail)
}
ret = append(ret, record)
}
}
leastloadSort(ret)
return ret
}
func leastloadSort(nodes []*node) {
sort.Slice(nodes, func(i, j int) bool {
left := nodes[i]
right := nodes[j]
if left.RTTDeviationCost != right.RTTDeviationCost {
return left.RTTDeviationCost < right.RTTDeviationCost
}
if left.RTTAverage != right.RTTAverage {
return left.RTTAverage < right.RTTAverage
}
if left.CountFail != right.CountFail {
return left.CountFail < right.CountFail
}
if left.CountAll != right.CountAll {
return left.CountAll > right.CountAll
}
return left.Tag < right.Tag
})
}

View File

@@ -0,0 +1,179 @@
package router
import (
"testing"
)
/*
Split into multiple package, need to be tested separately
func TestSelectLeastLoad(t *testing.T) {
settings := &StrategyLeastLoadConfig{
HealthCheck: &HealthPingConfig{
SamplingCount: 10,
},
Expected: 1,
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)
}
}
func TestSelectLeastLoadWithCost(t *testing.T) {
settings := &StrategyLeastLoadConfig{
HealthCheck: &HealthPingConfig{
SamplingCount: 10,
},
Costs: []*StrategyWeight{
{Match: "a", Value: 9},
},
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)
}
}
*/
func TestSelectLeastExpected(t *testing.T) {
strategy := &LeastLoadStrategy{
settings: &StrategyLeastLoadConfig{
Baselines: nil,
Expected: 3,
},
}
nodes := []*node{
{Tag: "a", RTTDeviationCost: 100},
{Tag: "b", RTTDeviationCost: 200},
{Tag: "c", RTTDeviationCost: 300},
{Tag: "d", RTTDeviationCost: 350},
}
expected := 3
ns := strategy.selectLeastLoad(nodes)
if len(ns) != expected {
t.Errorf("expected: %v, actual: %v", expected, len(ns))
}
}
func TestSelectLeastExpected2(t *testing.T) {
strategy := &LeastLoadStrategy{
settings: &StrategyLeastLoadConfig{
Baselines: nil,
Expected: 3,
},
}
nodes := []*node{
{Tag: "a", RTTDeviationCost: 100},
{Tag: "b", RTTDeviationCost: 200},
}
expected := 2
ns := strategy.selectLeastLoad(nodes)
if len(ns) != expected {
t.Errorf("expected: %v, actual: %v", expected, len(ns))
}
}
func TestSelectLeastExpectedAndBaselines(t *testing.T) {
strategy := &LeastLoadStrategy{
settings: &StrategyLeastLoadConfig{
Baselines: []int64{200, 300, 400},
Expected: 3,
},
}
nodes := []*node{
{Tag: "a", RTTDeviationCost: 100},
{Tag: "b", RTTDeviationCost: 200},
{Tag: "c", RTTDeviationCost: 250},
{Tag: "d", RTTDeviationCost: 300},
{Tag: "e", RTTDeviationCost: 310},
}
expected := 3
ns := strategy.selectLeastLoad(nodes)
if len(ns) != expected {
t.Errorf("expected: %v, actual: %v", expected, len(ns))
}
}
func TestSelectLeastExpectedAndBaselines2(t *testing.T) {
strategy := &LeastLoadStrategy{
settings: &StrategyLeastLoadConfig{
Baselines: []int64{200, 300, 400},
Expected: 3,
},
}
nodes := []*node{
{Tag: "a", RTTDeviationCost: 500},
{Tag: "b", RTTDeviationCost: 600},
{Tag: "c", RTTDeviationCost: 700},
{Tag: "d", RTTDeviationCost: 800},
{Tag: "e", RTTDeviationCost: 900},
}
expected := 3
ns := strategy.selectLeastLoad(nodes)
if len(ns) != expected {
t.Errorf("expected: %v, actual: %v", expected, len(ns))
}
}
func TestSelectLeastLoadBaselines(t *testing.T) {
strategy := &LeastLoadStrategy{
settings: &StrategyLeastLoadConfig{
Baselines: []int64{200, 400, 600},
Expected: 0,
},
}
nodes := []*node{
{Tag: "a", RTTDeviationCost: 100},
{Tag: "b", RTTDeviationCost: 200},
{Tag: "c", RTTDeviationCost: 300},
}
expected := 1
ns := strategy.selectLeastLoad(nodes)
if len(ns) != expected {
t.Errorf("expected: %v, actual: %v", expected, len(ns))
}
}
func TestSelectLeastLoadBaselinesNoQualified(t *testing.T) {
strategy := &LeastLoadStrategy{
settings: &StrategyLeastLoadConfig{
Baselines: []int64{200, 400, 600},
Expected: 0,
},
}
nodes := []*node{
{Tag: "a", RTTDeviationCost: 800},
{Tag: "b", RTTDeviationCost: 1000},
}
expected := 0
ns := strategy.selectLeastLoad(nodes)
if len(ns) != expected {
t.Errorf("expected: %v, actual: %v", expected, len(ns))
}
}

View File

@@ -14,6 +14,10 @@ type LeastPingStrategy struct {
observatory extension.Observatory
}
func (l *LeastPingStrategy) GetPrincipleTarget(strings []string) []string {
return []string{l.PickOutbound(strings)}
}
func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
l.ctx = ctx
}

View File

@@ -0,0 +1,21 @@
package router
import (
"github.com/xtls/xray-core/common/dice"
)
// RandomStrategy represents a random balancing strategy
type RandomStrategy struct{}
func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string {
return strings
}
func (s *RandomStrategy) PickOutbound(candidates []string) string {
count := len(candidates)
if count == 0 {
// goes to fallbackTag
return ""
}
return candidates[dice.Roll(count)]
}

89
app/router/weight.go Normal file
View File

@@ -0,0 +1,89 @@
package router
import (
"regexp"
"strconv"
"strings"
"sync"
)
type weightScaler func(value, weight float64) float64
var numberFinder = regexp.MustCompile(`\d+(\.\d+)?`)
// NewWeightManager creates a new WeightManager with settings
func NewWeightManager(s []*StrategyWeight, defaultWeight float64, scaler weightScaler) *WeightManager {
return &WeightManager{
settings: s,
cache: make(map[string]float64),
scaler: scaler,
defaultWeight: defaultWeight,
}
}
// WeightManager manages weights for specific settings
type WeightManager struct {
settings []*StrategyWeight
cache map[string]float64
scaler weightScaler
defaultWeight float64
mu sync.Mutex
}
// Get get the weight of specified tag
func (s *WeightManager) Get(tag string) float64 {
s.mu.Lock()
defer s.mu.Unlock()
weight, ok := s.cache[tag]
if ok {
return weight
}
weight = s.findValue(tag)
s.cache[tag] = weight
return weight
}
// Apply applies weight to the value
func (s *WeightManager) Apply(tag string, value float64) float64 {
return s.scaler(value, s.Get(tag))
}
func (s *WeightManager) findValue(tag string) float64 {
for _, w := range s.settings {
matched := s.getMatch(tag, w.Match, w.Regexp)
if matched == "" {
continue
}
if w.Value > 0 {
return float64(w.Value)
}
// auto weight from matched
numStr := numberFinder.FindString(matched)
if numStr == "" {
return s.defaultWeight
}
weight, err := strconv.ParseFloat(numStr, 64)
if err != nil {
newError("unexpected error from ParseFloat: ", err).AtError().WriteToLog()
return s.defaultWeight
}
return weight
}
return s.defaultWeight
}
func (s *WeightManager) getMatch(tag, find string, isRegexp bool) string {
if !isRegexp {
idx := strings.Index(tag, find)
if idx < 0 {
return ""
}
return find
}
r, err := regexp.Compile(find)
if err != nil {
newError("invalid regexp: ", find, "err: ", err).AtError().WriteToLog()
return ""
}
return r.FindString(tag)
}

60
app/router/weight_test.go Normal file
View File

@@ -0,0 +1,60 @@
package router_test
import (
"reflect"
"testing"
"github.com/xtls/xray-core/app/router"
)
func TestWeight(t *testing.T) {
manager := router.NewWeightManager(
[]*router.StrategyWeight{
{
Match: "x5",
Value: 100,
},
{
Match: "x8",
},
{
Regexp: true,
Match: `\bx0+(\.\d+)?\b`,
Value: 1,
},
{
Regexp: true,
Match: `\bx\d+(\.\d+)?\b`,
},
},
1, func(v, w float64) float64 {
return v * w
},
)
tags := []string{
"node name, x5, and more",
"node name, x8",
"node name, x15",
"node name, x0100, and more",
"node name, x10.1",
"node name, x00.1, and more",
}
// test weight
expected := []float64{100, 8, 15, 100, 10.1, 1}
actual := make([]float64, 0)
for _, tag := range tags {
actual = append(actual, manager.Get(tag))
}
if !reflect.DeepEqual(expected, actual) {
t.Errorf("expected: %v, actual: %v", expected, actual)
}
// test scale
expected2 := []float64{1000, 80, 150, 1000, 101, 10}
actual2 := make([]float64, 0)
for _, tag := range tags {
actual2 = append(actual2, manager.Apply(tag, 10))
}
if !reflect.DeepEqual(expected2, actual2) {
t.Errorf("expected2: %v, actual2: %v", expected2, actual2)
}
}

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/stats/command/command.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: app/stats/config.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/log/log.proto

View File

@@ -27,6 +27,11 @@ type generalLogger struct {
done *done.Instance
}
type serverityLogger struct {
inner *generalLogger
logLevel Severity
}
// NewLogger returns a generic log handler that can handle all type of messages.
func NewLogger(logWriterCreator WriterCreator) Handler {
return &generalLogger{
@@ -37,6 +42,32 @@ func NewLogger(logWriterCreator WriterCreator) Handler {
}
}
func ReplaceWithSeverityLogger(serverity Severity) {
w := CreateStdoutLogWriter()
g := &generalLogger{
creator: w,
buffer: make(chan Message, 16),
access: semaphore.New(1),
done: done.New(),
}
s := &serverityLogger{
inner: g,
logLevel: serverity,
}
RegisterHandler(s)
}
func (l *serverityLogger) Handle(msg Message) {
switch msg := msg.(type) {
case *GeneralMessage:
if msg.Severity <= l.logLevel {
l.inner.Handle(msg)
}
default:
l.inner.Handle(msg)
}
}
func (l *generalLogger) run() {
defer l.access.Signal()
@@ -67,6 +98,7 @@ func (l *generalLogger) run() {
}
func (l *generalLogger) Handle(msg Message) {
select {
case l.buffer <- msg:
default:

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/net/address.proto

View File

@@ -97,6 +97,35 @@ func (d Destination) NetAddr() string {
return addr
}
// RawNetAddr converts a net.Addr from its Destination presentation.
func (d Destination) RawNetAddr() net.Addr {
var addr net.Addr
switch d.Network {
case Network_TCP:
if d.Address.Family().IsIP() {
addr = &net.TCPAddr{
IP: d.Address.IP(),
Port: int(d.Port),
}
}
case Network_UDP:
if d.Address.Family().IsIP() {
addr = &net.UDPAddr{
IP: d.Address.IP(),
Port: int(d.Port),
}
}
case Network_UNIX:
if d.Address.Family().IsDomain() {
addr = &net.UnixAddr{
Name: d.Address.String(),
Net: d.Network.SystemString(),
}
}
}
return addr
}
// String returns the strings form of this Destination.
func (d Destination) String() string {
prefix := "unknown:"

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/net/destination.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/net/network.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/net/port.proto

View File

@@ -28,6 +28,9 @@ func GetOCSPStapling(cert [][]byte, path string) ([]byte, error) {
ocspData, err := GetOCSPForFile(path)
if err != nil {
ocspData, err = GetOCSPForCert(cert)
if err != nil {
return nil, err
}
if !CheckOCSPFileIsNotExist(path) {
err = os.Remove(path)
if err != nil {

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/protocol/headers.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/protocol/server_spec.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/protocol/user.proto

176
common/reflect/marshal.go Normal file
View File

@@ -0,0 +1,176 @@
package reflect
import (
"encoding/json"
"reflect"
cserial "github.com/xtls/xray-core/common/serial"
)
func MarshalToJson(v interface{}) (string, bool) {
if itf := marshalInterface(v, true); itf != nil {
if b, err := json.MarshalIndent(itf, "", " "); err == nil {
return string(b[:]), true
}
}
return "", false
}
func marshalTypedMessage(v *cserial.TypedMessage, ignoreNullValue bool) interface{} {
if v == nil {
return nil
}
tmsg, err := v.GetInstance()
if err != nil {
return nil
}
r := marshalInterface(tmsg, ignoreNullValue)
if msg, ok := r.(map[string]interface{}); ok {
msg["_TypedMessage_"] = v.Type
}
return r
}
func marshalSlice(v reflect.Value, ignoreNullValue bool) interface{} {
r := make([]interface{}, 0)
for i := 0; i < v.Len(); i++ {
rv := v.Index(i)
if rv.CanInterface() {
value := rv.Interface()
r = append(r, marshalInterface(value, ignoreNullValue))
}
}
return r
}
func marshalStruct(v reflect.Value, ignoreNullValue bool) interface{} {
r := make(map[string]interface{})
t := v.Type()
for i := 0; i < v.NumField(); i++ {
rv := v.Field(i)
if rv.CanInterface() {
ft := t.Field(i)
name := ft.Name
value := rv.Interface()
tv := marshalInterface(value, ignoreNullValue)
if tv != nil || !ignoreNullValue {
r[name] = tv
}
}
}
return r
}
func marshalMap(v reflect.Value, ignoreNullValue bool) interface{} {
// policy.level is map[uint32] *struct
kt := v.Type().Key()
vt := reflect.TypeOf((*interface{})(nil))
mt := reflect.MapOf(kt, vt)
r := reflect.MakeMap(mt)
for _, key := range v.MapKeys() {
rv := v.MapIndex(key)
if rv.CanInterface() {
iv := rv.Interface()
tv := marshalInterface(iv, ignoreNullValue)
if tv != nil || !ignoreNullValue {
r.SetMapIndex(key, reflect.ValueOf(&tv))
}
}
}
return r.Interface()
}
func marshalIString(v interface{}) (r string, ok bool) {
defer func() {
if err := recover(); err != nil {
r = ""
ok = false
}
}()
if iStringFn, ok := v.(interface{ String() string }); ok {
return iStringFn.String(), true
}
return "", false
}
func marshalKnownType(v interface{}, ignoreNullValue bool) (interface{}, bool) {
switch ty := v.(type) {
case cserial.TypedMessage:
return marshalTypedMessage(&ty, ignoreNullValue), true
case *cserial.TypedMessage:
return marshalTypedMessage(ty, ignoreNullValue), true
case map[string]json.RawMessage:
return ty, true
case []json.RawMessage:
return ty, true
case *json.RawMessage:
return ty, true
case json.RawMessage:
return ty, true
default:
return nil, false
}
}
func isValueKind(kind reflect.Kind) bool {
switch kind {
case reflect.Bool,
reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64,
reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Uintptr,
reflect.Float32,
reflect.Float64,
reflect.Complex64,
reflect.Complex128,
reflect.String:
return true
default:
return false
}
}
func marshalInterface(v interface{}, ignoreNullValue bool) interface{} {
if r, ok := marshalKnownType(v, ignoreNullValue); ok {
return r
}
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
k := rv.Kind()
if k == reflect.Invalid {
return nil
}
if isValueKind(k) {
return v
}
switch k {
case reflect.Struct:
return marshalStruct(rv, ignoreNullValue)
case reflect.Slice:
return marshalSlice(rv, ignoreNullValue)
case reflect.Array:
return marshalSlice(rv, ignoreNullValue)
case reflect.Map:
return marshalMap(rv, ignoreNullValue)
default:
break
}
if str, ok := marshalIString(v); ok {
return str
}
return nil
}

View File

@@ -0,0 +1,187 @@
package reflect_test
import (
"bytes"
"encoding/json"
"strings"
"testing"
. "github.com/xtls/xray-core/common/reflect"
cserial "github.com/xtls/xray-core/common/serial"
iserial "github.com/xtls/xray-core/infra/conf/serial"
)
func TestMashalStruct(t *testing.T) {
type Foo = struct {
N int `json:"n"`
Np *int `json:"np"`
S string `json:"s"`
Arr *[]map[string]map[string]string `json:"arr"`
}
n := 1
np := &n
arr := make([]map[string]map[string]string, 0)
m1 := make(map[string]map[string]string, 0)
m2 := make(map[string]string, 0)
m2["hello"] = "world"
m1["foo"] = m2
arr = append(arr, m1)
f1 := Foo{
N: n,
Np: np,
S: "hello",
Arr: &arr,
}
s, ok1 := MarshalToJson(f1)
sp, ok2 := MarshalToJson(&f1)
if !ok1 || !ok2 || s != sp {
t.Error("marshal failed")
}
f2 := Foo{}
if json.Unmarshal([]byte(s), &f2) != nil {
t.Error("json unmarshal failed")
}
v := (*f2.Arr)[0]["foo"]["hello"]
if f1.N != f2.N || *(f1.Np) != *(f2.Np) || f1.S != f2.S || v != "world" {
t.Error("f1 not equal to f2")
}
}
func TestMarshalConfigJson(t *testing.T) {
buf := bytes.NewBufferString(getConfig())
config, err := iserial.DecodeJSONConfig(buf)
if err != nil {
t.Error("decode JSON config failed")
}
bc, err := config.Build()
if err != nil {
t.Error("build core config failed")
}
tmsg := cserial.ToTypedMessage(bc)
tc, ok := MarshalToJson(tmsg)
if !ok {
t.Error("marshal config failed")
}
// t.Log(tc)
keywords := []string{
"4784f9b8-a879-4fec-9718-ebddefa47750",
"bing.com",
"DomainStrategy",
"InboundTag",
"Level",
"Stats",
"UserDownlink",
"UserUplink",
"System",
"InboundDownlink",
"OutboundUplink",
}
for _, kw := range keywords {
if !strings.Contains(tc, kw) {
t.Error("marshaled config error")
}
}
}
func getConfig() string {
return `{
"log": {
"loglevel": "debug"
},
"stats": {},
"policy": {
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true,
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
"inbounds": [
{
"tag": "agentin",
"protocol": "http",
"port": 8080,
"listen": "127.0.0.1",
"settings": {}
},
{
"listen": "127.0.0.1",
"port": 10085,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api-in"
}
],
"api": {
"tag": "api",
"services": [
"HandlerService",
"StatsService"
]
},
"routing": {
"rules": [
{
"inboundTag": [
"api-in"
],
"outboundTag": "api",
"type": "field"
}
],
"domainStrategy": "AsIs"
},
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "1.2.3.4",
"port": 1234,
"users": [
{
"id": "4784f9b8-a879-4fec-9718-ebddefa47750",
"encryption": "none"
}
]
}
]
},
"tag": "agentout",
"streamSettings": {
"network": "ws",
"security": "none",
"wsSettings": {
"path": "/?ed=2048",
"headers": {
"Host": "bing.com"
}
}
}
}
]
}`
}

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: common/serial/typed_message.proto

View File

@@ -24,6 +24,7 @@ const (
dispatcherKey
timeoutOnlyKey
allowedNetworkKey
handlerSessionKey
)
// ContextWithID returns a new context with the given ID.

View File

@@ -43,7 +43,7 @@ func NewOutboundDialer(outbound proxy.Outbound, dialer internet.Dialer) *XrayOut
}
func (d *XrayOutboundDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
ctx = session.ContextWithOutbound(context.Background(), &session.Outbound{
ctx = session.ContextWithOutbound(ctx, &session.Outbound{
Target: ToDestination(destination, ToNetwork(network)),
})
opts := []pipe.Option{pipe.WithSizeLimit(64 * 1024)}

View File

@@ -6,7 +6,9 @@ import (
"encoding/base64"
"fmt"
"io"
"strconv"
"strings"
"time"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net"
@@ -32,13 +34,16 @@ func init() {
if strings.ToLower(platform.NewEnvFlag(platform.XUDPLog).GetValue(func() string { return "" })) == "true" {
Show = true
}
rand.Read(BaseKey)
go func() {
time.Sleep(100 * time.Millisecond) // this is not nice, but need to give some time for Android to setup ENV
if raw := platform.NewEnvFlag(platform.XUDPBaseKey).GetValue(func() string { return "" }); raw != "" {
if BaseKey, _ = base64.RawURLEncoding.DecodeString(raw); len(BaseKey) == 32 {
return
}
panic(platform.XUDPBaseKey + ": invalid value: " + raw)
panic(platform.XUDPBaseKey + ": invalid value (BaseKey must be 32 bytes): " + raw + " len " + strconv.Itoa(len(BaseKey)))
}
rand.Read(BaseKey)
}()
}
func GetGlobalID(ctx context.Context) (globalID [8]byte) {

View File

@@ -24,10 +24,14 @@ type ConfigLoader func(input interface{}) (*Config, error)
// ConfigBuilder is a builder to build core.Config from filenames and formats
type ConfigBuilder func(files []string, formats []string) (*Config, error)
// ConfigMerger merge multiple json configs into on config
type ConfigsMerger func(files []string, formats []string) (string, error)
var (
configLoaderByName = make(map[string]*ConfigFormat)
configLoaderByExt = make(map[string]*ConfigFormat)
ConfigBuilderForFiles ConfigBuilder
ConfigMergedFormFiles ConfigsMerger
)
// RegisterConfigLoader add a new ConfigLoader.
@@ -49,6 +53,23 @@ func RegisterConfigLoader(format *ConfigFormat) error {
return nil
}
func GetMergedConfig(args cmdarg.Arg) (string, error) {
files := make([]string, 0)
formats := make([]string, 0)
supported := []string{"json", "yaml", "toml"}
for _, file := range args {
format := getFormat(file)
for _, s := range supported {
if s == format {
files = append(files, file)
formats = append(formats, format)
break
}
}
}
return ConfigMergedFormFiles(files, formats)
}
func GetFormatByExtension(ext string) string {
switch strings.ToLower(ext) {
case "pb", "protobuf":

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: core/config.proto

View File

@@ -21,7 +21,7 @@ import (
var (
Version_x byte = 1
Version_y byte = 8
Version_z byte = 6
Version_z byte = 8
)
var (

View File

@@ -0,0 +1,10 @@
package routing
type BalancerOverrider interface {
SetOverrideTarget(tag, target string) error
GetOverrideTarget(tag string) (string, error)
}
type BalancerPrincipleTarget interface {
GetPrincipleTarget(tag string) ([]string, error)
}

58
go.mod
View File

@@ -1,63 +1,61 @@
module github.com/xtls/xray-core
go 1.21.4
go 1.22
require (
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
github.com/golang/mock v1.6.0
github.com/golang/mock v1.7.0-rc.1
github.com/google/go-cmp v0.6.0
github.com/gorilla/websocket v1.5.1
github.com/miekg/dns v1.1.57
github.com/miekg/dns v1.1.58
github.com/pelletier/go-toml v1.9.5
github.com/pires/go-proxyproto v0.7.0
github.com/quic-go/quic-go v0.40.0
github.com/refraction-networking/utls v1.5.4
github.com/sagernet/sing v0.2.17
github.com/sagernet/sing-shadowsocks v0.2.5
github.com/quic-go/quic-go v0.41.0
github.com/refraction-networking/utls v1.6.3
github.com/sagernet/sing v0.3.2
github.com/sagernet/sing-shadowsocks v0.2.6
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
github.com/stretchr/testify v1.8.4
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230316163032-ced5aaba43e3
github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19
go4.org/netipx v0.0.0-20230824141953-6213f710f925
golang.org/x/crypto v0.15.0
golang.org/x/net v0.18.0
golang.org/x/sync v0.5.0
golang.org/x/sys v0.14.0
golang.zx2c4.com/wireguard v0.0.0-20231022001213-2e0774f246fb
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.31.0
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.19.0
golang.org/x/net v0.21.0
golang.org/x/sync v0.6.0
golang.org/x/sys v0.17.0
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
google.golang.org/grpc v1.62.0
google.golang.org/protobuf v1.32.0
gvisor.dev/gvisor v0.0.0-20231104011432-48a6d7d5bd0b
h12.io/socks v1.0.3
lukechampine.com/blake3 v1.2.1
)
require (
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/cloudflare/circl v1.3.6 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gaukas/godicttls v0.0.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/onsi/ginkgo/v2 v2.13.1 // indirect
github.com/google/pprof v0.0.0-20240225044709-fd706174c886 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
go.uber.org/mock v0.3.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/mod v0.14.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
go.uber.org/mock v0.4.0 // indirect
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
golang.org/x/mod v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.4.0 // indirect
golang.org/x/tools v0.15.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.18.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

130
go.sum
View File

@@ -8,15 +8,15 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -29,8 +29,6 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
@@ -45,8 +43,8 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@@ -63,8 +61,8 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20240225044709-fd706174c886 h1:JSJUTZTQT1Gzb2ROdAKOY3HwzBYcclS2GgumhMfHqjw=
github.com/google/pprof v0.0.0-20240225044709-fd706174c886/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -78,10 +76,10 @@ github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -92,16 +90,16 @@ github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU=
github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
@@ -116,19 +114,17 @@ github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.40.0 h1:GYd1iznlKm7dpHD7pOVpUvItgMPo/jrMgDWZhMCecqw=
github.com/quic-go/quic-go v0.40.0/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
github.com/refraction-networking/utls v1.5.4 h1:9k6EO2b8TaOGsQ7Pl7p9w6PUhx18/ZCeT0WNTZ7Uw4o=
github.com/refraction-networking/utls v1.5.4/go.mod h1:SPuDbBmgLGp8s+HLNc83FuavwZCFoMmExj+ltUHiHUw=
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
github.com/refraction-networking/utls v1.6.3 h1:MFOfRN35sSx6K5AZNIoESsBuBxS2LCgRilRIdHb6fDc=
github.com/refraction-networking/utls v1.6.3/go.mod h1:yil9+7qSl+gBwJqztoQseO6Pr3h62pQoY1lXiNR/FPs=
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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/sing v0.2.17 h1:vMPKb3MV0Aa5ws4dCJkRI8XEjrsUcDn810czd0FwmzI=
github.com/sagernet/sing v0.2.17/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
github.com/sagernet/sing-shadowsocks v0.2.5/go.mod h1:MGWGkcU2xW2G2mfArT9/QqpVLOGU+dBaahZCtPHdt7A=
github.com/sagernet/sing v0.3.2 h1:CwWcxUBPkMvwgfe2/zUgY5oHG9qOL8Aob/evIFYK9jo=
github.com/sagernet/sing v0.3.2/go.mod h1:qHySJ7u8po9DABtMYEkNBcOumx7ZZJf/fbv2sfTkNHE=
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@@ -168,33 +164,34 @@ github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49u
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230316163032-ced5aaba43e3 h1:tkMT5pTye+1NlKIXETU78NXw0fyjnaNHmJyyLyzw8+U=
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230316163032-ced5aaba43e3/go.mod h1:cAAsePK2e15YDAMJNyOpGYEWNe4sIghTY7gpz4cX/Ik=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19 h1:capMfFYRgH9BCLd6A3Er/cH3A9Nz3CU2KwxwOQZIePI=
github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ=
go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -205,9 +202,9 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -219,8 +216,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -229,39 +226,40 @@ golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
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/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20231022001213-2e0774f246fb h1:c5tyN8sSp8jSDxdCCDXVOpJwYXXhmTkNMt+g0zTSOic=
golang.zx2c4.com/wireguard v0.0.0-20231022001213-2e0774f246fb/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
@@ -274,18 +272,18 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c h1:NUsgEN92SQQqzfA+YtqYNqYmB3DMMYLlIwUZAQFVFbo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -7,6 +7,7 @@ import (
loggerservice "github.com/xtls/xray-core/app/log/command"
observatoryservice "github.com/xtls/xray-core/app/observatory/command"
handlerservice "github.com/xtls/xray-core/app/proxyman/command"
routerservice "github.com/xtls/xray-core/app/router/command"
statsservice "github.com/xtls/xray-core/app/stats/command"
"github.com/xtls/xray-core/common/serial"
)
@@ -34,6 +35,8 @@ func (c *APIConfig) Build() (*commander.Config, error) {
services = append(services, serial.ToTypedMessage(&statsservice.Config{}))
case "observatoryservice":
services = append(services, serial.ToTypedMessage(&observatoryservice.Config{}))
case "routingservice":
services = append(services, serial.ToTypedMessage(&routerservice.Config{}))
}
}

View File

@@ -17,6 +17,7 @@ type FreedomConfig struct {
Redirect string `json:"redirect"`
UserLevel uint32 `json:"userLevel"`
Fragment *Fragment `json:"fragment"`
ProxyProtocol uint32 `json:"proxyProtocol"`
}
type Fragment struct {
@@ -165,5 +166,8 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
config.DestinationOverride.Server.Address = v2net.NewIPOrDomain(v2net.ParseAddress(host))
}
}
if c.ProxyProtocol > 0 && c.ProxyProtocol <= 2 {
config.ProxyProtocol = c.ProxyProtocol
}
return config, nil
}

View File

@@ -1,9 +1,11 @@
package conf
import (
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
"google.golang.org/protobuf/proto"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/app/observatory/burst"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
)
type ObservatoryConfig struct {
@@ -16,3 +18,17 @@ type ObservatoryConfig struct {
func (o *ObservatoryConfig) Build() (proto.Message, error) {
return &observatory.Config{SubjectSelector: o.SubjectSelector, ProbeUrl: o.ProbeURL, ProbeInterval: int64(o.ProbeInterval), EnableConcurrency: o.EnableConcurrency}, nil
}
type BurstObservatoryConfig struct {
SubjectSelector []string `json:"subjectSelector"`
// health check settings
HealthCheck *healthCheckSettings `json:"pingConfig,omitempty"`
}
func (b BurstObservatoryConfig) Build() (proto.Message, error) {
if result, err := b.HealthCheck.Build(); err == nil {
return &burst.Config{SubjectSelector: b.SubjectSelector, PingConfig: result.(*burst.HealthPingConfig)}, nil
} else {
return nil, err
}
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/platform/filesystem"
"google.golang.org/protobuf/proto"
)
@@ -27,8 +28,10 @@ type BalancingRule struct {
Tag string `json:"tag"`
Selectors StringList `json:"selector"`
Strategy StrategyConfig `json:"strategy"`
FallbackTag string `json:"fallbackTag"`
}
// Build builds the balancing rule
func (r *BalancingRule) Build() (*router.BalancingRule, error) {
if r.Tag == "" {
return nil, newError("empty balancer tag")
@@ -37,20 +40,37 @@ func (r *BalancingRule) Build() (*router.BalancingRule, error) {
return nil, newError("empty selector list")
}
var strategy string
switch strings.ToLower(r.Strategy.Type) {
case strategyRandom, "":
strategy = strategyRandom
case strategyLeastPing:
strategy = "leastPing"
r.Strategy.Type = strings.ToLower(r.Strategy.Type)
switch r.Strategy.Type {
case "":
r.Strategy.Type = strategyRandom
case strategyRandom, strategyLeastLoad, strategyLeastPing, strategyRoundRobin:
default:
return nil, newError("unknown balancing strategy: " + r.Strategy.Type)
}
settings := []byte("{}")
if r.Strategy.Settings != nil {
settings = ([]byte)(*r.Strategy.Settings)
}
rawConfig, err := strategyConfigLoader.LoadWithID(settings, r.Strategy.Type)
if err != nil {
return nil, newError("failed to parse to strategy config.").Base(err)
}
var ts proto.Message
if builder, ok := rawConfig.(Buildable); ok {
ts, err = builder.Build()
if err != nil {
return nil, err
}
}
return &router.BalancingRule{
Strategy: r.Strategy.Type,
StrategySettings: serial.ToTypedMessage(ts),
FallbackTag: r.FallbackTag,
OutboundSelector: r.Selectors,
Tag: r.Tag,
OutboundSelector: []string(r.Selectors),
Strategy: strategy,
}, nil
}
@@ -636,7 +656,7 @@ func ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
if err != nil {
return nil, newError("invalid router rule").Base(err)
}
if strings.EqualFold(rawRule.Type, "field") {
if rawRule.Type == "" || strings.EqualFold(rawRule.Type, "field") {
fieldrule, err := parseFieldRule(msg)
if err != nil {
return nil, newError("invalid field rule").Base(err)

View File

@@ -1,6 +1,93 @@
package conf
import (
"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/infra/conf/cfgcommon/duration"
)
const (
strategyRandom string = "random"
strategyLeastPing string = "leastping"
strategyRoundRobin string = "roundrobin"
strategyLeastLoad string = "leastload"
)
var (
strategyConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
strategyRandom: func() interface{} { return new(strategyEmptyConfig) },
strategyLeastPing: func() interface{} { return new(strategyEmptyConfig) },
strategyRoundRobin: func() interface{} { return new(strategyEmptyConfig) },
strategyLeastLoad: func() interface{} { return new(strategyLeastLoadConfig) },
}, "type", "settings")
)
type strategyEmptyConfig struct {
}
func (v *strategyEmptyConfig) Build() (proto.Message, error) {
return nil, nil
}
type strategyLeastLoadConfig struct {
// weight settings
Costs []*router.StrategyWeight `json:"costs,omitempty"`
// ping rtt baselines
Baselines []duration.Duration `json:"baselines,omitempty"`
// expected nodes count to select
Expected int32 `json:"expected,omitempty"`
// max acceptable rtt, filter away high delay nodes. defalut 0
MaxRTT duration.Duration `json:"maxRTT,omitempty"`
// acceptable failure rate
Tolerance float64 `json:"tolerance,omitempty"`
}
// healthCheckSettings holds settings for health Checker
type healthCheckSettings struct {
Destination string `json:"destination"`
Connectivity string `json:"connectivity"`
Interval duration.Duration `json:"interval"`
SamplingCount int `json:"sampling"`
Timeout duration.Duration `json:"timeout"`
}
func (h healthCheckSettings) Build() (proto.Message, error) {
return &burst.HealthPingConfig{
Destination: h.Destination,
Connectivity: h.Connectivity,
Interval: int64(h.Interval),
Timeout: int64(h.Timeout),
SamplingCount: int32(h.SamplingCount),
}, nil
}
// Build implements Buildable.
func (v *strategyLeastLoadConfig) Build() (proto.Message, error) {
config := &router.StrategyLeastLoadConfig{}
config.Costs = v.Costs
config.Tolerance = float32(v.Tolerance)
if config.Tolerance < 0 {
config.Tolerance = 0
}
if config.Tolerance > 1 {
config.Tolerance = 1
}
config.Expected = v.Expected
if config.Expected < 0 {
config.Expected = 0
}
config.MaxRTT = int64(v.MaxRTT)
if config.MaxRTT < 0 {
config.MaxRTT = 0
}
config.Baselines = make([]int64, 0)
for _, b := range v.Baselines {
if b <= 0 {
continue
}
config.Baselines = append(config.Baselines, int64(b))
}
return config, nil
}

View File

@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"testing"
"time"
_ "unsafe"
"github.com/xtls/xray-core/app/router"
@@ -12,6 +13,7 @@ import (
"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/serial"
. "github.com/xtls/xray-core/infra/conf"
"google.golang.org/protobuf/proto"
)
@@ -96,6 +98,34 @@ func TestRouterConfig(t *testing.T) {
{
"tag": "b1",
"selector": ["test"]
},
{
"tag": "b2",
"selector": ["test"],
"strategy": {
"type": "leastload",
"settings": {
"healthCheck": {
"interval": "5m0s",
"sampling": 2,
"timeout": "5s",
"destination": "dest",
"connectivity": "conn"
},
"costs": [
{
"regexp": true,
"match": "\\d+(\\.\\d+)",
"value": 5
}
],
"baselines": ["400ms", "600ms"],
"expected": 6,
"maxRTT": "1000ms",
"tolerance": 0.5
}
},
"fallbackTag": "fall"
}
]
}`,
@@ -108,6 +138,28 @@ func TestRouterConfig(t *testing.T) {
OutboundSelector: []string{"test"},
Strategy: "random",
},
{
Tag: "b2",
OutboundSelector: []string{"test"},
Strategy: "leastload",
StrategySettings: serial.ToTypedMessage(&router.StrategyLeastLoadConfig{
Costs: []*router.StrategyWeight{
{
Regexp: true,
Match: "\\d+(\\.\\d+)",
Value: 5,
},
},
Baselines: []int64{
int64(time.Duration(400) * time.Millisecond),
int64(time.Duration(600) * time.Millisecond),
},
Expected: 6,
MaxRTT: int64(time.Duration(1000) * time.Millisecond),
Tolerance: 0.5,
}),
FallbackTag: "fall",
},
},
Rule: []*router.RoutingRule{
{

View File

@@ -3,12 +3,25 @@ package serial
import (
"io"
creflect "github.com/xtls/xray-core/common/reflect"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf"
"github.com/xtls/xray-core/main/confloader"
)
func BuildConfig(files []string, formats []string) (*core.Config, error) {
func MergeConfigFromFiles(files []string, formats []string) (string, error) {
c, err := mergeConfigs(files, formats)
if err != nil {
return "", err
}
if j, ok := creflect.MarshalToJson(c); ok {
return j, nil
}
return "", newError("marshal to json failed.").AtError()
}
func mergeConfigs(files []string, formats []string) (*conf.Config, error) {
cf := &conf.Config{}
for i, file := range files {
newError("Reading config: ", file).AtInfo().WriteToLog()
@@ -26,7 +39,15 @@ func BuildConfig(files []string, formats []string) (*core.Config, error) {
}
cf.Override(c, file)
}
return cf.Build()
return cf, nil
}
func BuildConfig(files []string, formats []string) (*core.Config, error) {
config, err := mergeConfigs(files, formats)
if err != nil {
return nil, err
}
return config.Build()
}
type readerDecoder func(io.Reader) (*conf.Config, error)
@@ -39,4 +60,5 @@ func init() {
ReaderDecoderByFormat["toml"] = DecodeTOMLConfig
core.ConfigBuilderForFiles = BuildConfig
core.ConfigMergedFormFiles = MergeConfigFromFiles
}

View File

@@ -357,6 +357,7 @@ type TLSConfig struct {
RejectUnknownSNI bool `json:"rejectUnknownSni"`
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"`
MasterKeyLog string `json:"masterKeyLog"`
}
// Build implements Buildable.
@@ -412,11 +413,14 @@ func (c *TLSConfig) Build() (proto.Message, error) {
}
}
config.MasterKeyLog = c.MasterKeyLog
return config, nil
}
type REALITYConfig struct {
Show bool `json:"show"`
MasterKeyLog string `json:"masterKeyLog"`
Dest json.RawMessage `json:"dest"`
Type string `json:"type"`
Xver uint64 `json:"xver"`
@@ -437,6 +441,7 @@ type REALITYConfig struct {
func (c *REALITYConfig) Build() (proto.Message, error) {
config := new(reality.Config)
config.Show = c.Show
config.MasterKeyLog = c.MasterKeyLog
var err error
if c.Dest != nil {
var i uint16

View File

@@ -2,8 +2,10 @@ package conf
import (
"encoding/json"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
"github.com/xtls/xray-core/common/net"
@@ -147,16 +149,14 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
if fb.Type == "" && fb.Dest != "" {
if fb.Dest == "serve-ws-none" {
fb.Type = "serve"
} else {
switch fb.Dest[0] {
case '@', '/':
} else if filepath.IsAbs(fb.Dest) || fb.Dest[0] == '@' {
fb.Type = "unix"
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
if strings.HasPrefix(fb.Dest, "@@") && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
copy(fullAddr, fb.Dest[1:])
fb.Dest = string(fullAddr)
}
default:
} else {
if _, err := strconv.Atoi(fb.Dest); err == nil {
fb.Dest = "127.0.0.1:" + fb.Dest
}
@@ -165,7 +165,6 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
}
}
}
}
if fb.Type == "" {
return nil, newError(`Trojan fallbacks: please fill in a valid value for every "dest"`)
}

View File

@@ -2,8 +2,10 @@ package conf
import (
"encoding/json"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
"github.com/xtls/xray-core/common/net"
@@ -103,16 +105,14 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
if fb.Type == "" && fb.Dest != "" {
if fb.Dest == "serve-ws-none" {
fb.Type = "serve"
} else {
switch fb.Dest[0] {
case '@', '/':
} else if filepath.IsAbs(fb.Dest) || fb.Dest[0] == '@' {
fb.Type = "unix"
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
if strings.HasPrefix(fb.Dest, "@@") && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
copy(fullAddr, fb.Dest[1:])
fb.Dest = string(fullAddr)
}
default:
} else {
if _, err := strconv.Atoi(fb.Dest); err == nil {
fb.Dest = "127.0.0.1:" + fb.Dest
}
@@ -121,7 +121,6 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
}
}
}
}
if fb.Type == "" {
return nil, newError(`VLESS fallbacks: please fill in a valid value for every "dest"`)
}

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/xtls/xray-core/app/dispatcher"
@@ -188,7 +189,7 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
} else {
// Listen on specific IP or Unix Domain Socket
receiverSettings.Listen = c.ListenOn.Build()
listenDS := c.ListenOn.Family().IsDomain() && (c.ListenOn.Domain()[0] == '/' || c.ListenOn.Domain()[0] == '@')
listenDS := c.ListenOn.Family().IsDomain() && (filepath.IsAbs(c.ListenOn.Domain()) || c.ListenOn.Domain()[0] == '@')
listenIP := c.ListenOn.Family().IsIP() || (c.ListenOn.Family().IsDomain() && c.ListenOn.Domain() == "localhost")
if listenIP {
// Listen on specific IP, must set PortList
@@ -409,6 +410,7 @@ type Config struct {
Reverse *ReverseConfig `json:"reverse"`
FakeDNS *FakeDNSConfig `json:"fakeDns"`
Observatory *ObservatoryConfig `json:"observatory"`
BurstObservatory *BurstObservatoryConfig `json:"burstObservatory"`
}
func (c *Config) findInboundTag(tag string) int {
@@ -638,6 +640,14 @@ func (c *Config) Build() (*core.Config, error) {
config.App = append(config.App, serial.ToTypedMessage(r))
}
if c.BurstObservatory != nil {
r, err := c.BurstObservatory.Build()
if err != nil {
return nil, err
}
config.App = append(config.App, serial.ToTypedMessage(r))
}
var inbounds []InboundDetourConfig
if c.InboundConfig != nil {

View File

@@ -15,6 +15,8 @@ var CmdAPI = &base.Command{
cmdGetStats,
cmdQueryStats,
cmdSysStats,
cmdBalancerInfo,
cmdBalancerOverride,
cmdAddInbounds,
cmdAddOutbounds,
cmdRemoveInbounds,

View File

@@ -0,0 +1,108 @@
package api
import (
"fmt"
"os"
"strings"
routerService "github.com/xtls/xray-core/app/router/command"
"github.com/xtls/xray-core/main/commands/base"
)
// TODO: support "-json" flag for json output
var cmdBalancerInfo = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api bi [--server=127.0.0.1:8080] [balancer]...",
Short: "balancer information",
Long: `
Get information of specified balancers, including health, strategy
and selecting. If no balancer tag specified, get information of
all balancers.
> Make sure you have "RoutingService" set in "config.api.services"
of server config.
Arguments:
-json
Use json output.
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout <seconds>
Timeout seconds to call API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 balancer1 balancer2
`,
Run: executeBalancerInfo,
}
func executeBalancerInfo(cmd *base.Command, args []string) {
setSharedFlags(cmd)
cmd.Flag.Parse(args)
conn, ctx, close := dialAPIServer()
defer close()
client := routerService.NewRoutingServiceClient(conn)
r := &routerService.GetBalancerInfoRequest{Tag: args[0]}
resp, err := client.GetBalancerInfo(ctx, r)
if err != nil {
base.Fatalf("failed to get health information: %s", err)
}
if apiJSON {
showJSONResponse(resp)
return
}
showBalancerInfo(resp.Balancer)
}
func showBalancerInfo(b *routerService.BalancerMsg) {
const tableIndent = 4
sb := new(strings.Builder)
// Override
if b.Override != nil {
sb.WriteString(" - Selecting Override:\n")
for i, s := range []string{b.Override.Target} {
writeRow(sb, tableIndent, i+1, []string{s}, nil)
}
}
// Selects
sb.WriteString(" - Selects:\n")
for i, o := range b.PrincipleTarget.Tag {
writeRow(sb, tableIndent, i+1, []string{o}, nil)
}
os.Stdout.WriteString(sb.String())
}
func getColumnFormats(titles []string) []string {
w := make([]string, len(titles))
for i, t := range titles {
w[i] = fmt.Sprintf("%%-%ds ", len(t))
}
return w
}
func writeRow(sb *strings.Builder, indent, index int, values, formats []string) {
if index == 0 {
// title line
sb.WriteString(strings.Repeat(" ", indent+4))
} else {
sb.WriteString(fmt.Sprintf("%s%-4d", strings.Repeat(" ", indent), index))
}
for i, v := range values {
format := "%-14s"
if i < len(formats) {
format = formats[i]
}
sb.WriteString(fmt.Sprintf(format, v))
}
sb.WriteByte('\n')
}

View File

@@ -0,0 +1,77 @@
package api
import (
routerService "github.com/xtls/xray-core/app/router/command"
"github.com/xtls/xray-core/main/commands/base"
)
var cmdBalancerOverride = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api bo [--server=127.0.0.1:8080] <-b balancer> outboundTag",
Short: "balancer override",
Long: `
Override a balancer's selection.
> Make sure you have "RoutingService" set in "config.api.services"
of server config.
Once a balancer's selecting is overridden:
- The balancer's selection result will always be outboundTag
Arguments:
-r, -remove
Remove the overridden
-r, -remove
Remove the override
-s, -server
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -b balancer tag
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -b balancer -r
`,
Run: executeBalancerOverride,
}
func executeBalancerOverride(cmd *base.Command, args []string) {
var (
balancer string
remove bool
)
cmd.Flag.StringVar(&balancer, "b", "", "")
cmd.Flag.StringVar(&balancer, "balancer", "", "")
cmd.Flag.BoolVar(&remove, "r", false, "")
cmd.Flag.BoolVar(&remove, "remove", false, "")
setSharedFlags(cmd)
cmd.Flag.Parse(args)
if balancer == "" {
base.Fatalf("balancer tag not specified")
}
conn, ctx, close := dialAPIServer()
defer close()
client := routerService.NewRoutingServiceClient(conn)
target := ""
if !remove {
target = cmd.Flag.Args()[0]
}
r := &routerService.OverrideBalancerTargetRequest{
BalancerTag: balancer,
Target: target,
}
_, err := client.OverrideBalancerTarget(ctx, r)
if err != nil {
base.Fatalf("failed to perform balancer health checks: %s", err)
}
}

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"google.golang.org/protobuf/encoding/protojson"
"io"
"net/http"
"net/url"
@@ -15,7 +16,6 @@ import (
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/main/commands/base"
"google.golang.org/grpc"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
)
@@ -24,6 +24,7 @@ type serviceHandler func(ctx context.Context, conn *grpc.ClientConn, cmd *base.C
var (
apiServerAddrPtr string
apiTimeout int
apiJSON bool
)
func setSharedFlags(cmd *base.Command) {
@@ -31,6 +32,7 @@ func setSharedFlags(cmd *base.Command) {
cmd.Flag.StringVar(&apiServerAddrPtr, "server", "127.0.0.1:8080", "")
cmd.Flag.IntVar(&apiTimeout, "t", 3, "")
cmd.Flag.IntVar(&apiTimeout, "timeout", 3, "")
cmd.Flag.BoolVar(&apiJSON, "json", false, "")
}
func dialAPIServer() (conn *grpc.ClientConn, ctx context.Context, close func()) {
@@ -103,13 +105,8 @@ func fetchHTTPContent(target string) ([]byte, error) {
return content, nil
}
func protoToJSONString(m proto.Message, _, indent string) (string, error) {
ops := protojson.MarshalOptions{
Indent: indent,
EmitUnpopulated: true,
}
b, err := ops.Marshal(m)
return string(b), err
func protoToJSONString(m proto.Message, prefix, indent string) (string, error) {
return strings.TrimSpace(protojson.MarshalOptions{Indent: indent}.Format(m)), nil
}
func showJSONResponse(m proto.Message) {

View File

@@ -16,5 +16,6 @@ func init() {
tls.CmdTLS,
cmdUUID,
cmdX25519,
cmdWG,
)
}

View File

@@ -0,0 +1,57 @@
package all
import (
"crypto/rand"
"encoding/base64"
"fmt"
"golang.org/x/crypto/curve25519"
)
func Curve25519Genkey(StdEncoding bool, input_base64 string) {
var output string
var err error
var privateKey, publicKey []byte
var encoding *base64.Encoding
if *input_stdEncoding || StdEncoding {
encoding = base64.StdEncoding
} else {
encoding = base64.RawURLEncoding
}
if len(input_base64) > 0 {
privateKey, err = encoding.DecodeString(input_base64)
if err != nil {
output = err.Error()
goto out
}
if len(privateKey) != curve25519.ScalarSize {
output = "Invalid length of private key."
goto out
}
}
if privateKey == nil {
privateKey = make([]byte, curve25519.ScalarSize)
if _, err = rand.Read(privateKey); err != nil {
output = err.Error()
goto out
}
}
// Modify random bytes using algorithm described at:
// https://cr.yp.to/ecdh.html.
privateKey[0] &= 248
privateKey[31] &= 127 | 64
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
output = err.Error()
goto out
}
output = fmt.Sprintf("Private key: %v\nPublic key: %v",
encoding.EncodeToString(privateKey),
encoding.EncodeToString(publicKey))
out:
fmt.Println(output)
}

27
main/commands/all/wg.go Normal file
View File

@@ -0,0 +1,27 @@
package all
import (
"github.com/xtls/xray-core/main/commands/base"
)
var cmdWG = &base.Command{
UsageLine: `{{.Exec}} wg [-i "private key (base64.StdEncoding)"]`,
Short: `Generate key pair for wireguard key exchange`,
Long: `
Generate key pair for wireguard key exchange.
Random: {{.Exec}} wg
From private key: {{.Exec}} wg -i "private key (base64.StdEncoding)"
`,
}
func init() {
cmdWG.Run = executeWG // break init loop
}
var input_wireguard = cmdWG.Flag.String("i", "", "")
func executeWG(cmd *base.Command, args []string) {
Curve25519Genkey(true, *input_wireguard)
}

View File

@@ -1,12 +1,7 @@
package all
import (
"crypto/rand"
"encoding/base64"
"fmt"
"github.com/xtls/xray-core/main/commands/base"
"golang.org/x/crypto/curve25519"
)
var cmdX25519 = &base.Command{
@@ -26,55 +21,9 @@ func init() {
cmdX25519.Run = executeX25519 // break init loop
}
var input_base64 = cmdX25519.Flag.String("i", "", "")
var input_stdEncoding = cmdX25519.Flag.Bool("std-encoding", false, "")
var input_x25519 = cmdX25519.Flag.String("i", "", "")
func executeX25519(cmd *base.Command, args []string) {
var output string
var err error
var privateKey []byte
var publicKey []byte
var encoding *base64.Encoding
if len(*input_base64) > 0 {
privateKey, err = base64.RawURLEncoding.DecodeString(*input_base64)
if err != nil {
output = err.Error()
goto out
}
if len(privateKey) != curve25519.ScalarSize {
output = "Invalid length of private key."
goto out
}
}
if privateKey == nil {
privateKey = make([]byte, curve25519.ScalarSize)
if _, err = rand.Read(privateKey); err != nil {
output = err.Error()
goto out
}
}
// Modify random bytes using algorithm described at:
// https://cr.yp.to/ecdh.html.
privateKey[0] &= 248
privateKey[31] &= 127
privateKey[31] |= 64
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
output = err.Error()
goto out
}
if *input_stdEncoding {
encoding = base64.StdEncoding
} else {
encoding = base64.RawURLEncoding
}
output = fmt.Sprintf("Private key: %v\nPublic key: %v",
encoding.EncodeToString(privateKey),
encoding.EncodeToString(publicKey))
out:
fmt.Println(output)
Curve25519Genkey(false, *input_x25519)
}

View File

@@ -12,8 +12,10 @@ import (
"runtime/debug"
"strings"
"syscall"
"time"
"github.com/xtls/xray-core/common/cmdarg"
clog "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/main/commands/base"
@@ -34,7 +36,9 @@ The -format=json flag sets the format of config files.
Default "auto".
The -test flag tells Xray to test config files only,
without launching the server
without launching the server.
The -dump flag tells Xray to print the merged config.
`,
}
@@ -45,6 +49,7 @@ func init() {
var (
configFiles cmdarg.Arg // "Config file for Xray.", the option is customed type, parse in main
configDir string
dump = cmdRun.Flag.Bool("dump", false, "Dump merged config only, without launching Xray server.")
test = cmdRun.Flag.Bool("test", false, "Test config file only, without launching Xray server.")
format = cmdRun.Flag.String("format", "auto", "Format of input file.")
@@ -61,6 +66,12 @@ var (
)
func executeRun(cmd *base.Command, args []string) {
if *dump {
clog.ReplaceWithSeverityLogger(clog.Severity_Warning)
errCode := dumpConfig()
os.Exit(errCode)
}
printVersion()
server, err := startXray()
if err != nil {
@@ -97,6 +108,18 @@ func executeRun(cmd *base.Command, args []string) {
}
}
func dumpConfig() int {
files := getConfigFilePath(false)
if config, err := core.GetMergedConfig(files); err != nil {
fmt.Println(err)
time.Sleep(1 * time.Second)
return 23
} else {
fmt.Print(config)
}
return 0
}
func fileExists(file string) bool {
info, err := os.Stat(file)
return err == nil && !info.IsDir()
@@ -139,12 +162,16 @@ func readConfDir(dirPath string) {
}
}
func getConfigFilePath() cmdarg.Arg {
func getConfigFilePath(verbose bool) cmdarg.Arg {
if dirExists(configDir) {
if verbose {
log.Println("Using confdir from arg:", configDir)
}
readConfDir(configDir)
} else if envConfDir := platform.GetConfDirPath(); dirExists(envConfDir) {
if verbose {
log.Println("Using confdir from env:", envConfDir)
}
readConfDir(envConfDir)
}
@@ -155,17 +182,23 @@ func getConfigFilePath() cmdarg.Arg {
if workingDir, err := os.Getwd(); err == nil {
configFile := filepath.Join(workingDir, "config.json")
if fileExists(configFile) {
if verbose {
log.Println("Using default config: ", configFile)
}
return cmdarg.Arg{configFile}
}
}
if configFile := platform.GetConfigurationPath(); fileExists(configFile) {
if verbose {
log.Println("Using config from env: ", configFile)
}
return cmdarg.Arg{configFile}
}
if verbose {
log.Println("Using config from STDIN")
}
return cmdarg.Arg{"stdin:"}
}
@@ -178,7 +211,7 @@ func getConfigFormat() string {
}
func startXray() (core.Server, error) {
configFiles := getConfigFilePath()
configFiles := getConfigFilePath(true)
// config, err := core.LoadConfig(getConfigFormat(), configFiles[0], configFiles)

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: proxy/blackhole/config.proto

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: proxy/dns/config.proto

View File

@@ -27,6 +27,9 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
h := new(Handler)
if err := core.RequireFeatures(ctx, func(dnsClient dns.Client, policyManager policy.Manager) error {
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
h.fdns = fdns
})
return h.Init(config.(*Config), dnsClient, policyManager)
}); err != nil {
return nil, err
@@ -41,6 +44,7 @@ type ownLinkVerifier interface {
type Handler struct {
client dns.Client
fdns dns.FakeDNSEngine
ownLinkVerifier ownLinkVerifier
server net.Destination
timeout time.Duration
@@ -179,7 +183,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet.
if isIPQuery {
go h.handleIPQuery(id, qType, domain, writer)
}
if isIPQuery || h.nonIPQuery == "drop" {
if isIPQuery || h.nonIPQuery == "drop" || qType == 65 {
b.Release()
continue
}
@@ -244,6 +248,10 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
return
}
if fkr0, ok := h.fdns.(dns.FakeDNSEngineRev0); ok && len(ips) > 0 && fkr0.IsIPInIPPool(net.IPAddress(ips[0])) {
ttl = 1
}
switch qType {
case dnsmessage.TypeA:
for i, ip := range ips {

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