mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-23 01:56:48 +08:00
Compare commits
103 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
37f8654957 | ||
![]() |
96ca298b2a | ||
![]() |
93cfbd6a92 | ||
![]() |
9b5c3f417e | ||
![]() |
d7434e8e36 | ||
![]() |
e7c5059a6f | ||
![]() |
cee776c3b7 | ||
![]() |
baf5de5cd3 | ||
![]() |
601246468a | ||
![]() |
6991c119e7 | ||
![]() |
da9c0ea07f | ||
![]() |
eefdcb27f3 | ||
![]() |
b0fa7b6b85 | ||
![]() |
87ef07d5f4 | ||
![]() |
a994bf8b04 | ||
![]() |
173b03448f | ||
![]() |
a3f50d0f5d | ||
![]() |
8fe8aa5432 | ||
![]() |
7184a8165f | ||
![]() |
aa101d9dc2 | ||
![]() |
c83c0bb21d | ||
![]() |
1c8375997d | ||
![]() |
57f0a6712f | ||
![]() |
d5e94deea6 | ||
![]() |
84d9c63bdb | ||
![]() |
51bacf7722 | ||
![]() |
3778a367c8 | ||
![]() |
a0f1e1f377 | ||
![]() |
c100d35b88 | ||
![]() |
f9653d0d88 | ||
![]() |
ad3dd3df56 | ||
![]() |
cae94570df | ||
![]() |
5ea1315b85 | ||
![]() |
fa5d7a255b | ||
![]() |
bf02392969 | ||
![]() |
a15334b395 | ||
![]() |
09656bd5d1 | ||
![]() |
40e41d8b6b | ||
![]() |
b091076bae | ||
![]() |
7c9e3f97f1 | ||
![]() |
c5713eb952 | ||
![]() |
7c8bec8596 | ||
![]() |
d83ccaeea9 | ||
![]() |
303beff5dd | ||
![]() |
3a99520370 | ||
![]() |
b56917fde5 | ||
![]() |
ad3d347cfc | ||
![]() |
dd635c7c8d | ||
![]() |
813f9a33b7 | ||
![]() |
d21e9b0abd | ||
![]() |
3167a70ff8 | ||
![]() |
25c531c6c3 | ||
![]() |
d97a29f55b | ||
![]() |
53de58fad3 | ||
![]() |
4bffd5114d | ||
![]() |
360272a77d | ||
![]() |
d20a835016 | ||
![]() |
10255bca83 | ||
![]() |
da5a28a088 | ||
![]() |
77376ed94f | ||
![]() |
7f7f57d3b6 | ||
![]() |
0ea2a50264 | ||
![]() |
961cf9d3b1 | ||
![]() |
2b08d8638e | ||
![]() |
81f9f567ff | ||
![]() |
2fa5c299ac | ||
![]() |
8a6b9e7420 | ||
![]() |
3f0bc13429 | ||
![]() |
9a2ab9b6a3 | ||
![]() |
2fc4b31fcf | ||
![]() |
7b4db50c9d | ||
![]() |
60f7a03e1b | ||
![]() |
44bb83033f | ||
![]() |
006cf491e5 | ||
![]() |
1dba70004f | ||
![]() |
1dc9a72068 | ||
![]() |
eacdda3c93 | ||
![]() |
b0bf0d7fd5 | ||
![]() |
b7f21be8bc | ||
![]() |
01c14a5994 | ||
![]() |
9becf02316 | ||
![]() |
f51bf98714 | ||
![]() |
5e19c1a778 | ||
![]() |
e03b78dcec | ||
![]() |
d60281d0a5 | ||
![]() |
5a5e615b46 | ||
![]() |
c01a30e8f4 | ||
![]() |
38b175d53e | ||
![]() |
53ac4c031d | ||
![]() |
31a8fae764 | ||
![]() |
46d6b9f57a | ||
![]() |
921be3ac40 | ||
![]() |
2da476eef4 | ||
![]() |
2c97beae4e | ||
![]() |
4e7a57ef86 | ||
![]() |
06734d6f08 | ||
![]() |
1444552691 | ||
![]() |
0c3e1d4bd9 | ||
![]() |
c590163f9f | ||
![]() |
2fd765ea4c | ||
![]() |
be21b1194b | ||
![]() |
69cbb4c47a | ||
![]() |
6f092bd212 |
43
.github/workflows/release.yml
vendored
43
.github/workflows/release.yml
vendored
@@ -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: |
|
||||
|
12
.github/workflows/test.yml
vendored
12
.github/workflows/test.yml
vendored
@@ -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
2
.gitignore
vendored
@@ -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
29
Makefile
Normal 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
|
21
README.md
21
README.md
@@ -22,18 +22,20 @@
|
||||
|
||||
- Linux Script
|
||||
- [XTLS/Xray-install](https://github.com/XTLS/Xray-install)
|
||||
- [team-cloudchaser/tempest](https://github.com/team-cloudchaser/tempest) (supports [`systemd`](https://systemd.io) and [OpenRC](https://github.com/OpenRC/openrc); Linux-only)
|
||||
- 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 +58,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
|
||||
|
||||
@@ -99,6 +102,7 @@
|
||||
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
|
||||
- [XrayKit](https://github.com/arror/XrayKit)
|
||||
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
|
||||
- [xray-api](https://github.com/XVGuardian/xray-api)
|
||||
- [XrayR](https://github.com/XrayR-project/XrayR)
|
||||
- [XrayR-release](https://github.com/XrayR-project/XrayR-release)
|
||||
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
|
||||
@@ -123,16 +127,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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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() {
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -181,9 +181,7 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
|
||||
}
|
||||
|
||||
// Normalize the FQDN form query
|
||||
if strings.HasSuffix(domain, ".") {
|
||||
domain = domain[:len(domain)-1]
|
||||
}
|
||||
domain = strings.TrimSuffix(domain, ".")
|
||||
|
||||
// Static host lookup
|
||||
switch addrs := s.hosts.Lookup(domain, option); {
|
||||
@@ -215,7 +213,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
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"net/url"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -24,7 +26,7 @@ import (
|
||||
|
||||
// NextProtoDQ - During connection establishment, DNS/QUIC support is indicated
|
||||
// by selecting the ALPN token "dq" in the crypto handshake.
|
||||
const NextProtoDQ = "doq-i00"
|
||||
const NextProtoDQ = "doq"
|
||||
|
||||
const handshakeTimeout = time.Second * 8
|
||||
|
||||
@@ -194,13 +196,18 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
|
||||
return
|
||||
}
|
||||
|
||||
dnsReqBuf := buf.New()
|
||||
binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||
dnsReqBuf.Write(b.Bytes())
|
||||
b.Release()
|
||||
|
||||
conn, err := s.openStream(dnsCtx)
|
||||
if err != nil {
|
||||
newError("failed to open quic connection").Base(err).AtError().WriteToLog()
|
||||
return
|
||||
}
|
||||
|
||||
_, err = conn.Write(b.Bytes())
|
||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||
if err != nil {
|
||||
newError("failed to send query").Base(err).AtError().WriteToLog()
|
||||
return
|
||||
@@ -210,9 +217,21 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
|
||||
|
||||
respBuf := buf.New()
|
||||
defer respBuf.Release()
|
||||
n, err := respBuf.ReadFrom(conn)
|
||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||
if err != nil && n == 0 {
|
||||
newError("failed to read response").Base(err).AtError().WriteToLog()
|
||||
newError("failed to read response length").Base(err).AtError().WriteToLog()
|
||||
return
|
||||
}
|
||||
var length int16
|
||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||
if err != nil {
|
||||
newError("failed to parse response length").Base(err).AtError().WriteToLog()
|
||||
return
|
||||
}
|
||||
respBuf.Clear()
|
||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||
if err != nil && n == 0 {
|
||||
newError("failed to read response length").Base(err).AtError().WriteToLog()
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
14
app/observatory/burst/burst.go
Normal file
14
app/observatory/burst/burst.go
Normal 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
|
||||
)
|
108
app/observatory/burst/burstobserver.go
Normal file
108
app/observatory/burst/burstobserver.go
Normal 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))
|
||||
}))
|
||||
}
|
276
app/observatory/burst/config.pb.go
Normal file
276
app/observatory/burst/config.pb.go
Normal 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
|
||||
}
|
29
app/observatory/burst/config.proto
Normal file
29
app/observatory/burst/config.proto
Normal 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;
|
||||
}
|
9
app/observatory/burst/errors.generated.go
Normal file
9
app/observatory/burst/errors.generated.go
Normal 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{})
|
||||
}
|
253
app/observatory/burst/healthping.go
Normal file
253
app/observatory/burst/healthping.go
Normal file
@@ -0,0 +1,253 @@
|
||||
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() {
|
||||
tags, err := selector()
|
||||
if err != nil {
|
||||
newError("error select outbounds for initial health check: ", err).AtWarning().WriteToLog()
|
||||
return
|
||||
}
|
||||
h.Check(tags)
|
||||
}()
|
||||
|
||||
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
|
||||
}
|
143
app/observatory/burst/healthping_result.go
Normal file
143
app/observatory/burst/healthping_result.go
Normal 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
|
||||
}
|
106
app/observatory/burst/healthping_result_test.go
Normal file
106
app/observatory/burst/healthping_result_test.go
Normal 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)
|
||||
}
|
||||
}
|
69
app/observatory/burst/ping.go
Normal file
69
app/observatory/burst/ping.go
Normal 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
|
||||
}
|
@@ -1,6 +1,3 @@
|
||||
//go:build !confonly
|
||||
// +build !confonly
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
@@ -90,13 +177,14 @@ type OutboundStatus struct {
|
||||
LastSeenTime int64 `protobuf:"varint,5,opt,name=last_seen_time,json=lastSeenTime,proto3" json:"last_seen_time,omitempty"`
|
||||
// @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"`
|
||||
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
|
||||
(*ObservationResult)(nil), // 0: xray.core.app.observatory.ObservationResult
|
||||
(*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,
|
||||
},
|
||||
|
@@ -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{
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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()
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
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
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
tags := hs.Select(b.selectors)
|
||||
if len(tags) == 0 {
|
||||
return "", newError("no available outbounds selected")
|
||||
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")
|
||||
}
|
||||
|
50
app/router/balancing_override.go
Normal file
50
app/router/balancing_override.go
Normal 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 = ""
|
||||
}
|
@@ -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{
|
||||
|
@@ -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
|
||||
(*RoutingContext)(nil), // 0: xray.app.router.command.RoutingContext
|
||||
(*SubscribeRoutingStatsRequest)(nil), // 1: xray.app.router.command.SubscribeRoutingStatsRequest
|
||||
(*TestRouteRequest)(nil), // 2: xray.app.router.command.TestRouteRequest
|
||||
(*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
|
||||
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
|
||||
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
|
||||
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,
|
||||
},
|
||||
|
@@ -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 {}
|
||||
|
@@ -19,8 +19,10 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
RoutingService_SubscribeRoutingStats_FullMethodName = "/xray.app.router.command.RoutingService/SubscribeRoutingStats"
|
||||
RoutingService_TestRoute_FullMethodName = "/xray.app.router.command.RoutingService/TestRoute"
|
||||
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{
|
||||
{
|
||||
|
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"github.com/xtls/xray-core/testing/mocks"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/test/bufconn"
|
||||
)
|
||||
|
||||
@@ -80,7 +81,7 @@ func TestServiceSubscribeRoutingStats(t *testing.T) {
|
||||
// Client goroutine
|
||||
go func() {
|
||||
defer lis.Close()
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
@@ -214,7 +215,7 @@ func TestServiceSubscribeSubsetOfFields(t *testing.T) {
|
||||
// Client goroutine
|
||||
go func() {
|
||||
defer lis.Close()
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
@@ -318,7 +319,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) {
|
||||
@@ -337,7 +338,7 @@ func TestSerivceTestRoute(t *testing.T) {
|
||||
// Client goroutine
|
||||
go func() {
|
||||
defer lis.Close()
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
|
@@ -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")
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
@@ -707,9 +708,11 @@ type BalancingRule struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
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"`
|
||||
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,29 +1264,32 @@ 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
|
||||
(*Domain)(nil), // 2: xray.app.router.Domain
|
||||
(*CIDR)(nil), // 3: xray.app.router.CIDR
|
||||
(*GeoIP)(nil), // 4: xray.app.router.GeoIP
|
||||
(*GeoIPList)(nil), // 5: xray.app.router.GeoIPList
|
||||
(*GeoSite)(nil), // 6: xray.app.router.GeoSite
|
||||
(*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
|
||||
(Domain_Type)(0), // 0: xray.app.router.Domain.Type
|
||||
(Config_DomainStrategy)(0), // 1: xray.app.router.Config.DomainStrategy
|
||||
(*Domain)(nil), // 2: xray.app.router.Domain
|
||||
(*CIDR)(nil), // 3: xray.app.router.CIDR
|
||||
(*GeoIP)(nil), // 4: xray.app.router.GeoIP
|
||||
(*GeoIPList)(nil), // 5: xray.app.router.GeoIPList
|
||||
(*GeoSite)(nil), // 6: xray.app.router.GeoSite
|
||||
(*GeoSiteList)(nil), // 7: xray.app.router.GeoSiteList
|
||||
(*RoutingRule)(nil), // 8: xray.app.router.RoutingRule
|
||||
(*BalancingRule)(nil), // 9: xray.app.router.BalancingRule
|
||||
(*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,
|
||||
},
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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))
|
||||
|
200
app/router/strategy_leastload.go
Normal file
200
app/router/strategy_leastload.go
Normal 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
|
||||
})
|
||||
}
|
179
app/router/strategy_leastload_test.go
Normal file
179
app/router/strategy_leastload_test.go
Normal 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))
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
|
21
app/router/strategy_random.go
Normal file
21
app/router/strategy_random.go
Normal 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
89
app/router/weight.go
Normal 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
60
app/router/weight_test.go
Normal 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)
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -178,7 +178,7 @@ func (r *AuthenticationReader) readInternal(soft bool, mb *buf.MultiBuffer) erro
|
||||
if size <= buf.Size {
|
||||
b, err := r.readBuffer(int32(size), int32(padding))
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
*mb = append(*mb, b)
|
||||
return nil
|
||||
|
@@ -4,7 +4,6 @@ package dice // import "github.com/xtls/xray-core/common/dice"
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Roll returns a non-negative number between 0 (inclusive) and n (exclusive).
|
||||
@@ -46,7 +45,3 @@ func (dd *DeterministicDice) Roll(n int) int {
|
||||
}
|
||||
return dd.Intn(n)
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@ package drain
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/xtls/xray-core/common/dice"
|
||||
)
|
||||
@@ -36,7 +35,7 @@ func (d *BehaviorSeedLimitedDrainer) Drain(reader io.Reader) error {
|
||||
}
|
||||
|
||||
func drainReadN(reader io.Reader, n int) error {
|
||||
_, err := io.CopyN(ioutil.Discard, reader, int64(n))
|
||||
_, err := io.CopyN(io.Discard, reader, int64(n))
|
||||
return err
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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:"
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
176
common/reflect/marshal.go
Normal 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
|
||||
}
|
187
common/reflect/marshal_test.go
Normal file
187
common/reflect/marshal_test.go
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}`
|
||||
}
|
@@ -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
|
||||
|
||||
|
@@ -24,6 +24,7 @@ const (
|
||||
dispatcherKey
|
||||
timeoutOnlyKey
|
||||
allowedNetworkKey
|
||||
handlerSessionKey
|
||||
)
|
||||
|
||||
// ContextWithID returns a new context with the given ID.
|
||||
|
@@ -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)}
|
||||
|
@@ -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
|
||||
}
|
||||
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)
|
||||
}
|
||||
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 (BaseKey must be 32 bytes): " + raw + " len " + strconv.Itoa(len(BaseKey)))
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func GetGlobalID(ctx context.Context) (globalID [8]byte) {
|
||||
|
@@ -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":
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
var (
|
||||
Version_x byte = 1
|
||||
Version_y byte = 8
|
||||
Version_z byte = 6
|
||||
Version_z byte = 9
|
||||
)
|
||||
|
||||
var (
|
||||
|
10
features/routing/balancer.go
Normal file
10
features/routing/balancer.go
Normal 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)
|
||||
}
|
62
go.mod
62
go.mod
@@ -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.6
|
||||
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/stretchr/testify v1.9.0
|
||||
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.21.0
|
||||
golang.org/x/net v0.22.0
|
||||
golang.org/x/sync v0.6.0
|
||||
golang.org/x/sys v0.18.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
google.golang.org/grpc v1.62.1
|
||||
google.golang.org/protobuf v1.33.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/golang/protobuf v1.5.4 // 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-20240227163752-401108e1b7e7 // indirect
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.16.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.16.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.19.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-20240308144416-29370a3891b7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
147
go.sum
147
go.sum
@@ -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,15 +29,13 @@ 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=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -45,26 +43,24 @@ 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=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
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-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/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 +74,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 +88,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.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM=
|
||||
github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
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 +112,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.6 h1:dsEdYLKBQlrxUfw1a92x0VdPvR1/BOxQ+HIMyaoEJsQ=
|
||||
github.com/sagernet/sing v0.3.6/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
||||
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=
|
||||
@@ -159,8 +153,8 @@ github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
||||
@@ -168,33 +162,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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
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.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||
golang.org/x/mod v0.16.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 +200,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.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
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 +214,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 +224,39 @@ 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.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.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.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||
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 +269,16 @@ 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-20240308144416-29370a3891b7 h1:em/y72n4XlYRtayY/cVj6pnVzHa//BDA1BdoO+z9mdE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
||||
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/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/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.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=
|
||||
|
@@ -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{}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -6,7 +6,8 @@ import (
|
||||
)
|
||||
|
||||
type GRPCConfig struct {
|
||||
ServiceName string `json:"serviceName" `
|
||||
Authority string `json:"authority"`
|
||||
ServiceName string `json:"serviceName"`
|
||||
MultiMode bool `json:"multiMode"`
|
||||
IdleTimeout int32 `json:"idle_timeout"`
|
||||
HealthCheckTimeout int32 `json:"health_check_timeout"`
|
||||
@@ -28,6 +29,7 @@ func (g *GRPCConfig) Build() (proto.Message, error) {
|
||||
}
|
||||
|
||||
return &grpc.Config{
|
||||
Authority: g.Authority,
|
||||
ServiceName: g.ServiceName,
|
||||
MultiMode: g.MultiMode,
|
||||
IdleTimeout: g.IdleTimeout,
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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"
|
||||
)
|
||||
@@ -24,11 +25,13 @@ type StrategyConfig struct {
|
||||
}
|
||||
|
||||
type BalancingRule struct {
|
||||
Tag string `json:"tag"`
|
||||
Selectors StringList `json:"selector"`
|
||||
Strategy StrategyConfig `json:"strategy"`
|
||||
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)
|
||||
|
@@ -1,6 +1,93 @@
|
||||
package conf
|
||||
|
||||
const (
|
||||
strategyRandom string = "random"
|
||||
strategyLeastPing string = "leastping"
|
||||
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
|
||||
}
|
||||
|
@@ -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{
|
||||
{
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -7,14 +7,15 @@ import (
|
||||
)
|
||||
|
||||
type TransportConfig struct {
|
||||
TCPConfig *TCPConfig `json:"tcpSettings"`
|
||||
KCPConfig *KCPConfig `json:"kcpSettings"`
|
||||
WSConfig *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPConfig *HTTPConfig `json:"httpSettings"`
|
||||
DSConfig *DomainSocketConfig `json:"dsSettings"`
|
||||
QUICConfig *QUICConfig `json:"quicSettings"`
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
TCPConfig *TCPConfig `json:"tcpSettings"`
|
||||
KCPConfig *KCPConfig `json:"kcpSettings"`
|
||||
WSConfig *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPConfig *HTTPConfig `json:"httpSettings"`
|
||||
DSConfig *DomainSocketConfig `json:"dsSettings"`
|
||||
QUICConfig *QUICConfig `json:"quicSettings"`
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
HTTPUPGRADEConfig *HttpUpgradeConfig `json:"httpupgradeSettings"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -101,5 +102,16 @@ func (c *TransportConfig) Build() (*global.Config, error) {
|
||||
})
|
||||
}
|
||||
|
||||
if c.HTTPUPGRADEConfig != nil {
|
||||
hs, err := c.HTTPUPGRADEConfig.Build()
|
||||
if err != nil {
|
||||
return nil, newError("failed to build HttpUpgrade config").Base(err)
|
||||
}
|
||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
||||
ProtocolName: "httpupgrade",
|
||||
Settings: serial.ToTypedMessage(hs),
|
||||
})
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/xtls/xray-core/transport/internet/domainsocket"
|
||||
httpheader "github.com/xtls/xray-core/transport/internet/headers/http"
|
||||
"github.com/xtls/xray-core/transport/internet/http"
|
||||
"github.com/xtls/xray-core/transport/internet/httpupgrade"
|
||||
"github.com/xtls/xray-core/transport/internet/kcp"
|
||||
"github.com/xtls/xray-core/transport/internet/quic"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
@@ -181,6 +182,24 @@ func (c *WebSocketConfig) Build() (proto.Message, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type HttpUpgradeConfig struct {
|
||||
Path string `json:"path"`
|
||||
Host string `json:"host"`
|
||||
AcceptProxyProtocol bool `json:"acceptProxyProtocol"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
func (c *HttpUpgradeConfig) Build() (proto.Message, error) {
|
||||
config := &httpupgrade.Config{
|
||||
Path: c.Path,
|
||||
Host: c.Host,
|
||||
}
|
||||
if c.AcceptProxyProtocol {
|
||||
config.AcceptProxyProtocol = c.AcceptProxyProtocol
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type HTTPConfig struct {
|
||||
Host *StringList `json:"host"`
|
||||
Path string `json:"path"`
|
||||
@@ -357,6 +376,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 +432,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 +460,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
|
||||
@@ -601,6 +625,8 @@ func (p TransportProtocol) Build() (string, error) {
|
||||
return "quic", nil
|
||||
case "grpc", "gun":
|
||||
return "grpc", nil
|
||||
case "httpupgrade":
|
||||
return "httpupgrade", nil
|
||||
default:
|
||||
return "", newError("Config: unknown transport protocol: ", p)
|
||||
}
|
||||
@@ -701,19 +727,20 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||
}
|
||||
|
||||
type StreamConfig struct {
|
||||
Network *TransportProtocol `json:"network"`
|
||||
Security string `json:"security"`
|
||||
TLSSettings *TLSConfig `json:"tlsSettings"`
|
||||
REALITYSettings *REALITYConfig `json:"realitySettings"`
|
||||
TCPSettings *TCPConfig `json:"tcpSettings"`
|
||||
KCPSettings *KCPConfig `json:"kcpSettings"`
|
||||
WSSettings *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPSettings *HTTPConfig `json:"httpSettings"`
|
||||
DSSettings *DomainSocketConfig `json:"dsSettings"`
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
SocketSettings *SocketConfig `json:"sockopt"`
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
Network *TransportProtocol `json:"network"`
|
||||
Security string `json:"security"`
|
||||
TLSSettings *TLSConfig `json:"tlsSettings"`
|
||||
REALITYSettings *REALITYConfig `json:"realitySettings"`
|
||||
TCPSettings *TCPConfig `json:"tcpSettings"`
|
||||
KCPSettings *KCPConfig `json:"kcpSettings"`
|
||||
WSSettings *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPSettings *HTTPConfig `json:"httpSettings"`
|
||||
DSSettings *DomainSocketConfig `json:"dsSettings"`
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
SocketSettings *SocketConfig `json:"sockopt"`
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
HTTPUPGRADESettings *HttpUpgradeConfig `json:"httpupgradeSettings"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -834,6 +861,16 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
Settings: serial.ToTypedMessage(gs),
|
||||
})
|
||||
}
|
||||
if c.HTTPUPGRADESettings != nil {
|
||||
hs, err := c.HTTPUPGRADESettings.Build()
|
||||
if err != nil {
|
||||
return nil, newError("Failed to build HttpUpgrade config.").Base(err)
|
||||
}
|
||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
||||
ProtocolName: "httpupgrade",
|
||||
Settings: serial.ToTypedMessage(hs),
|
||||
})
|
||||
}
|
||||
if c.SocketSettings != nil {
|
||||
ss, err := c.SocketSettings.Build()
|
||||
if err != nil {
|
||||
|
@@ -2,8 +2,10 @@ package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@@ -147,22 +149,19 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
|
||||
if fb.Type == "" && fb.Dest != "" {
|
||||
if fb.Dest == "serve-ws-none" {
|
||||
fb.Type = "serve"
|
||||
} else if filepath.IsAbs(fb.Dest) || fb.Dest[0] == '@' {
|
||||
fb.Type = "unix"
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
switch fb.Dest[0] {
|
||||
case '@', '/':
|
||||
fb.Type = "unix"
|
||||
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && (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:
|
||||
if _, err := strconv.Atoi(fb.Dest); err == nil {
|
||||
fb.Dest = "127.0.0.1:" + fb.Dest
|
||||
}
|
||||
if _, _, err := net.SplitHostPort(fb.Dest); err == nil {
|
||||
fb.Type = "tcp"
|
||||
}
|
||||
if _, err := strconv.Atoi(fb.Dest); err == nil {
|
||||
fb.Dest = "127.0.0.1:" + fb.Dest
|
||||
}
|
||||
if _, _, err := net.SplitHostPort(fb.Dest); err == nil {
|
||||
fb.Type = "tcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,10 @@ package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@@ -103,22 +105,19 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
||||
if fb.Type == "" && fb.Dest != "" {
|
||||
if fb.Dest == "serve-ws-none" {
|
||||
fb.Type = "serve"
|
||||
} else if filepath.IsAbs(fb.Dest) || fb.Dest[0] == '@' {
|
||||
fb.Type = "unix"
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
switch fb.Dest[0] {
|
||||
case '@', '/':
|
||||
fb.Type = "unix"
|
||||
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && (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:
|
||||
if _, err := strconv.Atoi(fb.Dest); err == nil {
|
||||
fb.Dest = "127.0.0.1:" + fb.Dest
|
||||
}
|
||||
if _, _, err := net.SplitHostPort(fb.Dest); err == nil {
|
||||
fb.Type = "tcp"
|
||||
}
|
||||
if _, err := strconv.Atoi(fb.Dest); err == nil {
|
||||
fb.Dest = "127.0.0.1:" + fb.Dest
|
||||
}
|
||||
if _, _, err := net.SplitHostPort(fb.Dest); err == nil {
|
||||
fb.Type = "tcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
@@ -542,6 +544,9 @@ func applyTransportConfig(s *StreamConfig, t *TransportConfig) {
|
||||
if s.DSSettings == nil {
|
||||
s.DSSettings = t.DSConfig
|
||||
}
|
||||
if s.HTTPUPGRADESettings == nil {
|
||||
s.HTTPUPGRADESettings = t.HTTPUPGRADEConfig
|
||||
}
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -638,6 +643,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 {
|
||||
|
@@ -15,6 +15,8 @@ var CmdAPI = &base.Command{
|
||||
cmdGetStats,
|
||||
cmdQueryStats,
|
||||
cmdSysStats,
|
||||
cmdBalancerInfo,
|
||||
cmdBalancerOverride,
|
||||
cmdAddInbounds,
|
||||
cmdAddOutbounds,
|
||||
cmdRemoveInbounds,
|
||||
|
108
main/commands/all/api/balancer_info.go
Normal file
108
main/commands/all/api/balancer_info.go
Normal 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')
|
||||
}
|
77
main/commands/all/api/balancer_override.go
Normal file
77
main/commands/all/api/balancer_override.go
Normal 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)
|
||||
}
|
||||
}
|
@@ -12,10 +12,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
|
||||
"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 +26,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,11 +34,12 @@ 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()) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(apiTimeout)*time.Second)
|
||||
conn, err := grpc.DialContext(ctx, apiServerAddrPtr, grpc.WithInsecure(), grpc.WithBlock())
|
||||
conn, err := grpc.DialContext(ctx, apiServerAddrPtr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
|
||||
if err != nil {
|
||||
base.Fatalf("failed to dial %s", apiServerAddrPtr)
|
||||
}
|
||||
@@ -103,13 +107,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) {
|
||||
|
@@ -16,5 +16,6 @@ func init() {
|
||||
tls.CmdTLS,
|
||||
cmdUUID,
|
||||
cmdX25519,
|
||||
cmdWG,
|
||||
)
|
||||
}
|
||||
|
57
main/commands/all/curve25519.go
Normal file
57
main/commands/all/curve25519.go
Normal 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)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user