mirror of
https://github.com/daeuniverse/dae.git
synced 2024-12-22 20:04:40 +07:00
feat: add config_parser
This commit is contained in:
parent
916a55d480
commit
edbce81e88
17
Makefile
17
Makefile
@ -6,14 +6,25 @@
|
||||
# The development version of clang is distributed as the 'clang' binary,
|
||||
# while stable/released versions have a version number attached.
|
||||
# Pin the default clang to a stable version.
|
||||
CLANG ?= clang
|
||||
CLANG ?= clang-14
|
||||
STRIP ?= llvm-strip
|
||||
CFLAGS := -O2 -g -Wall -Werror $(CFLAGS)
|
||||
#CFLAGS := -O2 -g -Wall -Werror $(CFLAGS)
|
||||
CFLAGS := -O2 -Wall -Werror $(CFLAGS)
|
||||
|
||||
# Get version from .git.
|
||||
date=$(shell git log -1 --format="%cd" --date=short | sed s/-//g)
|
||||
count=$(shell git rev-list --count HEAD)
|
||||
commit=$(shell git rev-parse --short HEAD)
|
||||
ifeq ($(wildcard .git/.),)
|
||||
version=unstable-0.nogit
|
||||
else
|
||||
version=unstable-$(date).r$(count).$(commit)
|
||||
endif
|
||||
|
||||
.PHONY: ebpf dae
|
||||
|
||||
dae: ebpf
|
||||
go build -ldflags "-s -w" .
|
||||
go build -ldflags "-s -w -X github.com/v2rayA/dae/cmd.Version=$(version)" .
|
||||
|
||||
# $BPF_CLANG is used in go:generate invocations.
|
||||
ebpf: export BPF_CLANG := $(CLANG)
|
||||
|
@ -10,6 +10,9 @@ As a successor of [v2rayA](https://github.com/v2rayA/v2rayA), dae abandoned v2ra
|
||||
|
||||
## TODO
|
||||
|
||||
1. Dns upstream. Check dns upstream and source loop (whether upstream is also a client of us) and remind user to add source rule.
|
||||
1. Check dns upstream and source loop (whether upstream is also a client of us) and remind the user to add sip rule.
|
||||
1. Domain routing performance optimization.
|
||||
1. Support not operator for RoutingA rule.
|
||||
1. DisableL4Checksum by link.
|
||||
1. Config file.
|
||||
1. ...
|
||||
|
113
cmd/cmd.go
Normal file
113
cmd/cmd.go
Normal file
@ -0,0 +1,113 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
"github.com/v2rayA/dae/component/control"
|
||||
"github.com/v2rayA/dae/component/outbound"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/pkg/logger"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
v *viper.Viper
|
||||
Version = "unknown"
|
||||
verbose int
|
||||
rootCmd = &cobra.Command{
|
||||
Use: "dae [flags] [command [argument ...]]",
|
||||
Short: "dae is a lightweight and high-performance transparent proxy solution.",
|
||||
Long: `dae is a lightweight and high-performance transparent proxy solution.`,
|
||||
Version: Version,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
const (
|
||||
tproxyPort = 12345
|
||||
ifname = "docker0"
|
||||
)
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
log := logger.NewLogger(2)
|
||||
log.Println("Running")
|
||||
|
||||
d, err := dialer.NewFromLink(log, "socks5://localhost:1080#proxy")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
group := outbound.NewDialerGroup(log, "proxy",
|
||||
[]*dialer.Dialer{d},
|
||||
outbound.DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_MinAverage10Latencies,
|
||||
})
|
||||
t, err := control.NewControlPlane(log, []*outbound.DialerGroup{group}, `
|
||||
#sip(172.17.0.2)->proxy
|
||||
#mac("02:42:ac:11:00:02")->block
|
||||
#ipversion(4)->proxy
|
||||
#l4proto(tcp)->proxy
|
||||
#ip(119.29.29.29) -> proxy
|
||||
#ip(223.5.5.5) -> direct
|
||||
ip(geoip:cn) -> direct
|
||||
|
||||
domain(full:google.com) && port(443) && l4proto(tcp) -> proxy
|
||||
|
||||
domain(geosite:cn, suffix:"ip.sb") -> direct
|
||||
#ip("91.105.192.0/23","91.108.4.0/22","91.108.8.0/21","91.108.16.0/21","91.108.56.0/22","95.161.64.0/20","149.154.160.0/20","185.76.151.0/24")->proxy
|
||||
#domain(geosite:category-scholar-!cn, geosite:category-scholar-cn)->direct
|
||||
final: proxy
|
||||
`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = t.BindLink(ifname); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGILL)
|
||||
go func() {
|
||||
if err := t.ListenAndServe(tproxyPort); err != nil {
|
||||
log.Errorln("ListenAndServe:", err)
|
||||
sigs <- nil
|
||||
}
|
||||
}()
|
||||
<-sigs
|
||||
if e := t.Close(); e != nil {
|
||||
log.Errorln("Close control plane:", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Execute executes the root command.
|
||||
func Execute() error {
|
||||
return rootCmd.Execute()
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().CountVarP(&verbose, "verbose", "v", "verbose (-v, or -vv)")
|
||||
|
||||
rootCmd.PersistentFlags().StringP("node", "n", "", "node share-link of your modern proxy")
|
||||
rootCmd.PersistentFlags().StringP("subscription", "s", "", "subscription-link of your modern proxy")
|
||||
rootCmd.PersistentFlags().Bool("noudp", false, "do not redirect UDP traffic, even though the proxy server supports")
|
||||
rootCmd.PersistentFlags().String("testnode", "true", "test the connectivity before connecting to the node")
|
||||
rootCmd.PersistentFlags().Bool("select", false, "manually select the node to connect from the subscription")
|
||||
//rootCmd.AddCommand(configCmd)
|
||||
}
|
||||
|
||||
func NewLogger(verbose int) *logrus.Logger {
|
||||
log := logrus.New()
|
||||
|
||||
var level logrus.Level
|
||||
switch verbose {
|
||||
case 0:
|
||||
level = logrus.WarnLevel
|
||||
case 1:
|
||||
level = logrus.InfoLevel
|
||||
default:
|
||||
level = logrus.TraceLevel
|
||||
}
|
||||
log.SetLevel(level)
|
||||
|
||||
return log
|
||||
}
|
43
cmd/infra/su.go
Normal file
43
cmd/infra/su.go
Normal file
@ -0,0 +1,43 @@
|
||||
package infra
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func AutoSu() {
|
||||
if os.Getuid() == 0 {
|
||||
return
|
||||
}
|
||||
program := filepath.Base(os.Args[0])
|
||||
pathSudo, err := exec.LookPath("sudo")
|
||||
if err != nil {
|
||||
// skip
|
||||
return
|
||||
}
|
||||
// https://github.com/WireGuard/wireguard-tools/blob/71799a8f6d1450b63071a21cad6ed434b348d3d5/src/wg-quick/linux.bash#L85
|
||||
p, err := os.StartProcess(pathSudo, append([]string{
|
||||
pathSudo,
|
||||
"-E",
|
||||
"-p",
|
||||
fmt.Sprintf("%v must be run as root. Please enter the password for %%u to continue: ", program),
|
||||
"--",
|
||||
}, os.Args...), &os.ProcAttr{
|
||||
Files: []*os.File{
|
||||
os.Stdin,
|
||||
os.Stdout,
|
||||
os.Stderr,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
stat, err := p.Wait()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(stat.ExitCode())
|
||||
}
|
@ -20,8 +20,6 @@ const (
|
||||
BigEndianTproxyPortKey
|
||||
DisableL4TxChecksumKey
|
||||
DisableL4RxChecksumKey
|
||||
EpochKey
|
||||
RoutingsLenKey
|
||||
)
|
||||
|
||||
type DisableL4ChecksumPolicy uint32
|
||||
@ -50,6 +48,7 @@ type OutboundIndex uint8
|
||||
|
||||
const (
|
||||
OutboundDirect OutboundIndex = 0
|
||||
OutboundBlock OutboundIndex = 1
|
||||
OutboundControlPlaneDirect OutboundIndex = 0xFE
|
||||
OutboundLogicalAnd OutboundIndex = 0xFF
|
||||
)
|
||||
@ -58,6 +57,8 @@ func (i OutboundIndex) String() string {
|
||||
switch i {
|
||||
case OutboundDirect:
|
||||
return "direct"
|
||||
case OutboundBlock:
|
||||
return "block"
|
||||
case OutboundControlPlaneDirect:
|
||||
return "<Control Plane Direct>"
|
||||
case OutboundLogicalAnd:
|
||||
|
@ -19,4 +19,6 @@ const (
|
||||
Function_Mac = "mac"
|
||||
Function_L4Proto = "l4proto"
|
||||
Function_IpVersion = "ipversion"
|
||||
|
||||
Declaration_Final = "final"
|
||||
)
|
||||
|
28
common/debug.go
Normal file
28
common/debug.go
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2023, mzz2017 (mzz@tuta.io). All rights reserved.
|
||||
*/
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ReportMemory(tag string) {
|
||||
if !logrus.IsLevelEnabled(logrus.DebugLevel) {
|
||||
return
|
||||
}
|
||||
b, err := os.ReadFile(filepath.Join("/proc", strconv.Itoa(os.Getpid()), "status"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
str := strings.TrimSpace(string(b))
|
||||
_, after, _ := strings.Cut(str, "VmHWM:")
|
||||
usage, _, _ := strings.Cut(after, "\n")
|
||||
logrus.Debugln(tag+": memory usage:", strings.TrimSpace(usage))
|
||||
}
|
@ -16,7 +16,7 @@ type bpfLpmKey struct {
|
||||
Data [4]uint32
|
||||
}
|
||||
|
||||
func (o *bpfObjects) NewLpmMap(keys []bpfLpmKey, values []uint32) (m *ebpf.Map, err error) {
|
||||
func (o *bpfObjects) newLpmMap(keys []bpfLpmKey, values []uint32) (m *ebpf.Map, err error) {
|
||||
m, err = ebpf.NewMap(&ebpf.MapSpec{
|
||||
Type: ebpf.LPMTrie,
|
||||
Flags: o.UnusedLpmType.Flags(),
|
@ -6,4 +6,4 @@
|
||||
package control
|
||||
|
||||
// $BPF_CLANG and $BPF_CFLAGS are set by the Makefile.
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -strip $BPF_STRIP -cflags $BPF_CFLAGS bpf kern/tproxy.c -- -I../headers
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -strip $BPF_STRIP -cflags $BPF_CFLAGS bpf kern/tproxy.c --
|
||||
|
@ -42,31 +42,31 @@ type ControlPlane struct {
|
||||
Final string
|
||||
|
||||
// mutex protects the dnsCache.
|
||||
mutex sync.Mutex
|
||||
dnsCache map[string]*dnsCache
|
||||
// Deprecated
|
||||
epoch uint32
|
||||
mutex sync.Mutex
|
||||
dnsCache map[string]*dnsCache
|
||||
dnsUpstream netip.AddrPort
|
||||
|
||||
deferFuncs []func() error
|
||||
}
|
||||
|
||||
func NewControlPlane(log *logrus.Logger, routingA string) (*ControlPlane, error) {
|
||||
func NewControlPlane(log *logrus.Logger, dialerGroups []*outbound.DialerGroup, routingA string) (*ControlPlane, error) {
|
||||
// Allow the current process to lock memory for eBPF resources.
|
||||
if err := rlimit.RemoveMemlock(); err != nil {
|
||||
return nil, fmt.Errorf("rlimit.RemoveMemlock:%v", err)
|
||||
}
|
||||
pinPath := filepath.Join(consts.BpfPinRoot, consts.AppName)
|
||||
os.MkdirAll(pinPath, 0755)
|
||||
|
||||
// Load pre-compiled programs and maps into the kernel.
|
||||
var bpf bpfObjects
|
||||
retry_load:
|
||||
retryLoadBpf:
|
||||
if err := loadBpfObjects(&bpf, &ebpf.CollectionOptions{
|
||||
Maps: ebpf.MapOptions{
|
||||
PinPath: pinPath,
|
||||
},
|
||||
}); err != nil {
|
||||
if errors.Is(err, ebpf.ErrMapIncompatible) {
|
||||
// Map property is incompatible. Remove the old map and try again.
|
||||
prefix := "use pinned map "
|
||||
_, after, ok := strings.Cut(err.Error(), prefix)
|
||||
if !ok {
|
||||
@ -75,72 +75,35 @@ retry_load:
|
||||
mapName, _, _ := strings.Cut(after, ":")
|
||||
_ = os.Remove(filepath.Join(pinPath, mapName))
|
||||
log.Warnf("New map format was incompatible with existing map %v, and the old one was removed.", mapName)
|
||||
goto retry_load
|
||||
goto retryLoadBpf
|
||||
}
|
||||
return nil, fmt.Errorf("loading objects: %w", err)
|
||||
}
|
||||
|
||||
// Flush dst_map.
|
||||
//_ = os.Remove(filepath.Join(pinPath, "dst_map"))
|
||||
//if err := bpf.ParamMap.Update(consts.IpsLenKey, uint32(1), ebpf.UpdateAny); err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
//if err := bpf.ParamMap.Update(consts.BigEndianTproxyPortKey, uint32(swap16(tproxyPort)), ebpf.UpdateAny); err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
// Write params.
|
||||
if err := bpf.ParamMap.Update(consts.DisableL4TxChecksumKey, consts.DisableL4ChecksumPolicy_SetZero, ebpf.UpdateAny); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := bpf.ParamMap.Update(consts.DisableL4RxChecksumKey, consts.DisableL4ChecksumPolicy_SetZero, ebpf.UpdateAny); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//var epoch uint32
|
||||
//bpf.ParamMap.Lookup(consts.EpochKey, &epoch)
|
||||
//epoch++
|
||||
//if err := bpf.ParamMap.Update(consts.EpochKey, epoch, ebpf.UpdateAny); err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
//if err := bpf.ParamMap.Update(consts.InterfaceIpParamOff, binary.LittleEndian.Uint32([]byte{172, 17, 0, 1}), ebpf.UpdateAny); err != nil { // 172.17.0.1
|
||||
// return nil, err
|
||||
//}
|
||||
//if err := bpf.ParamMap.Update(InterfaceIpParamOff+1, binary.LittleEndian.Uint32([]byte{10, 249, 40, 166}), ebpf.UpdateAny); err != nil { // 10.249.40.166
|
||||
// log.Println(err)
|
||||
// return
|
||||
//}
|
||||
//if err := bpf.ParamMap.Update(InterfaceIpParamOff+2, binary.LittleEndian.Uint32([]byte{10, 250, 52, 180}), ebpf.UpdateAny); err != nil { // 10.250.52.180
|
||||
// log.Println(err)
|
||||
// return
|
||||
//}
|
||||
|
||||
cfDnsAddr := netip.AddrFrom4([4]byte{1, 1, 1, 1})
|
||||
cfDnsAddr16 := cfDnsAddr.As16()
|
||||
cfDnsPort := uint16(53)
|
||||
if err := bpf.DnsUpstreamMap.Update(consts.ZeroKey, bpfIpPort{
|
||||
Ip: common.Ipv6ByteSliceToUint32Array(cfDnsAddr16[:]),
|
||||
Port: swap16(cfDnsPort),
|
||||
}, ebpf.UpdateAny); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/**/
|
||||
// TODO:
|
||||
d, err := dialer.NewFromLink("socks5://localhost:1080#proxy")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// DialerGroups (outbounds).
|
||||
outbounds := []*outbound.DialerGroup{
|
||||
outbound.NewDialerGroup(log, consts.OutboundDirect.String(),
|
||||
[]*dialer.Dialer{dialer.FullconeDirectDialer},
|
||||
[]*dialer.Dialer{dialer.NewDirectDialer(log, true)},
|
||||
outbound.DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_Fixed,
|
||||
FixedIndex: 0,
|
||||
}),
|
||||
outbound.NewDialerGroup(log, "proxy",
|
||||
[]*dialer.Dialer{d},
|
||||
outbound.NewDialerGroup(log, consts.OutboundBlock.String(),
|
||||
[]*dialer.Dialer{dialer.NewBlockDialer(log)},
|
||||
outbound.DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_MinAverage10Latencies,
|
||||
Policy: consts.DialerSelectionPolicy_Fixed,
|
||||
FixedIndex: 0,
|
||||
}),
|
||||
}
|
||||
outbounds = append(outbounds, dialerGroups...)
|
||||
// Generate outboundName2Id from outbounds.
|
||||
if len(outbounds) > 0xff {
|
||||
return nil, fmt.Errorf("too many outbounds")
|
||||
@ -177,7 +140,17 @@ retry_load:
|
||||
if err := builder.Build(); err != nil {
|
||||
return nil, fmt.Errorf("RoutingMatcherBuilder.Build: %w", err)
|
||||
}
|
||||
/**/
|
||||
|
||||
// DNS upstream.
|
||||
cfDnsAddr := netip.AddrFrom4([4]byte{1, 1, 1, 1})
|
||||
cfDnsAddr16 := cfDnsAddr.As16()
|
||||
cfDnsPort := uint16(53)
|
||||
if err := bpf.DnsUpstreamMap.Update(consts.ZeroKey, bpfIpPort{
|
||||
Ip: common.Ipv6ByteSliceToUint32Array(cfDnsAddr16[:]),
|
||||
Port: swap16(cfDnsPort),
|
||||
}, ebpf.UpdateAny); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ControlPlane{
|
||||
log: log,
|
||||
@ -190,8 +163,7 @@ retry_load:
|
||||
mutex: sync.Mutex{},
|
||||
dnsCache: make(map[string]*dnsCache),
|
||||
dnsUpstream: netip.AddrPortFrom(cfDnsAddr, cfDnsPort),
|
||||
//epoch: epoch,
|
||||
deferFuncs: []func() error{bpf.Close},
|
||||
deferFuncs: []func() error{bpf.Close},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -235,9 +207,26 @@ func (c *ControlPlane) BindLink(ifname string) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err := c.bpf.IfindexIpMap.Update(uint32(link.Attrs().Index), linkIp, ebpf.UpdateAny); err != nil {
|
||||
if err := c.bpf.IfindexTproxyIpMap.Update(uint32(link.Attrs().Index), linkIp, ebpf.UpdateAny); err != nil {
|
||||
return fmt.Errorf("update IfindexIpsMap: %w", err)
|
||||
}
|
||||
// FIXME: not only this link ip.
|
||||
if linkIp.HasIp4 {
|
||||
if err := c.bpf.HostIpLpm.Update(bpfLpmKey{
|
||||
PrefixLen: 128,
|
||||
Data: linkIp.Ip4,
|
||||
}, uint32(1), ebpf.UpdateAny); err != nil {
|
||||
return fmt.Errorf("update IfindexIpsMap: %w", err)
|
||||
}
|
||||
}
|
||||
if linkIp.HasIp6 {
|
||||
if err := c.bpf.HostIpLpm.Update(bpfLpmKey{
|
||||
PrefixLen: 128,
|
||||
Data: linkIp.Ip6,
|
||||
}, uint32(1), ebpf.UpdateAny); err != nil {
|
||||
return fmt.Errorf("update IfindexIpsMap: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Insert qdisc and filters.
|
||||
qdisc := &netlink.GenericQdisc{
|
||||
|
@ -7,9 +7,9 @@ package control
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
"github.com/cilium/ebpf"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"net/netip"
|
||||
"strings"
|
||||
@ -53,7 +53,6 @@ func (c *ControlPlane) BatchUpdateDomainRouting(cache *dnsCache) error {
|
||||
keys = append(keys, common.Ipv6ByteSliceToUint32Array(ip6[:]))
|
||||
vals = append(vals, bpfDomainRouting{
|
||||
Bitmap: cache.DomainBitmap,
|
||||
Epoch: c.epoch,
|
||||
})
|
||||
}
|
||||
if _, err := c.bpf.DomainRoutingMap.BatchUpdate(keys, vals, &ebpf.BatchOptions{
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func (c *ControlPlane) MatchDomainBitmap(domain string) (bitmap [consts.MaxRoutingLen / 32]uint32) {
|
||||
// FIXME: high performance implementation.
|
||||
// TODO: high performance implementation.
|
||||
for _, s := range c.SimulatedDomainSet {
|
||||
for _, d := range s.Domains {
|
||||
var hit bool
|
99
component/control/kern/bpf_endian.h
Normal file
99
component/control/kern/bpf_endian.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_ENDIAN__
|
||||
#define __BPF_ENDIAN__
|
||||
|
||||
/*
|
||||
* Isolate byte #n and put it into byte #m, for __u##b type.
|
||||
* E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64:
|
||||
* 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx
|
||||
* 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000
|
||||
* 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn
|
||||
* 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000
|
||||
*/
|
||||
#define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8))
|
||||
|
||||
#define ___bpf_swab16(x) ((__u16)( \
|
||||
___bpf_mvb(x, 16, 0, 1) | \
|
||||
___bpf_mvb(x, 16, 1, 0)))
|
||||
|
||||
#define ___bpf_swab32(x) ((__u32)( \
|
||||
___bpf_mvb(x, 32, 0, 3) | \
|
||||
___bpf_mvb(x, 32, 1, 2) | \
|
||||
___bpf_mvb(x, 32, 2, 1) | \
|
||||
___bpf_mvb(x, 32, 3, 0)))
|
||||
|
||||
#define ___bpf_swab64(x) ((__u64)( \
|
||||
___bpf_mvb(x, 64, 0, 7) | \
|
||||
___bpf_mvb(x, 64, 1, 6) | \
|
||||
___bpf_mvb(x, 64, 2, 5) | \
|
||||
___bpf_mvb(x, 64, 3, 4) | \
|
||||
___bpf_mvb(x, 64, 4, 3) | \
|
||||
___bpf_mvb(x, 64, 5, 2) | \
|
||||
___bpf_mvb(x, 64, 6, 1) | \
|
||||
___bpf_mvb(x, 64, 7, 0)))
|
||||
|
||||
/* LLVM's BPF target selects the endianness of the CPU
|
||||
* it compiles on, or the user specifies (bpfel/bpfeb),
|
||||
* respectively. The used __BYTE_ORDER__ is defined by
|
||||
* the compiler, we cannot rely on __BYTE_ORDER from
|
||||
* libc headers, since it doesn't reflect the actual
|
||||
* requested byte order.
|
||||
*
|
||||
* Note, LLVM's BPF target has different __builtin_bswapX()
|
||||
* semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
|
||||
* in bpfel and bpfeb case, which means below, that we map
|
||||
* to cpu_to_be16(). We could use it unconditionally in BPF
|
||||
* case, but better not rely on it, so that this header here
|
||||
* can be used from application and BPF program side, which
|
||||
* use different targets.
|
||||
*/
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define __bpf_ntohs(x) __builtin_bswap16(x)
|
||||
# define __bpf_htons(x) __builtin_bswap16(x)
|
||||
# define __bpf_constant_ntohs(x) ___bpf_swab16(x)
|
||||
# define __bpf_constant_htons(x) ___bpf_swab16(x)
|
||||
# define __bpf_ntohl(x) __builtin_bswap32(x)
|
||||
# define __bpf_htonl(x) __builtin_bswap32(x)
|
||||
# define __bpf_constant_ntohl(x) ___bpf_swab32(x)
|
||||
# define __bpf_constant_htonl(x) ___bpf_swab32(x)
|
||||
# define __bpf_be64_to_cpu(x) __builtin_bswap64(x)
|
||||
# define __bpf_cpu_to_be64(x) __builtin_bswap64(x)
|
||||
# define __bpf_constant_be64_to_cpu(x) ___bpf_swab64(x)
|
||||
# define __bpf_constant_cpu_to_be64(x) ___bpf_swab64(x)
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define __bpf_ntohs(x) (x)
|
||||
# define __bpf_htons(x) (x)
|
||||
# define __bpf_constant_ntohs(x) (x)
|
||||
# define __bpf_constant_htons(x) (x)
|
||||
# define __bpf_ntohl(x) (x)
|
||||
# define __bpf_htonl(x) (x)
|
||||
# define __bpf_constant_ntohl(x) (x)
|
||||
# define __bpf_constant_htonl(x) (x)
|
||||
# define __bpf_be64_to_cpu(x) (x)
|
||||
# define __bpf_cpu_to_be64(x) (x)
|
||||
# define __bpf_constant_be64_to_cpu(x) (x)
|
||||
# define __bpf_constant_cpu_to_be64(x) (x)
|
||||
#else
|
||||
# error "Fix your compiler's __BYTE_ORDER__?!"
|
||||
#endif
|
||||
|
||||
#define bpf_htons(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_htons(x) : __bpf_htons(x))
|
||||
#define bpf_ntohs(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_ntohs(x) : __bpf_ntohs(x))
|
||||
#define bpf_htonl(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_htonl(x) : __bpf_htonl(x))
|
||||
#define bpf_ntohl(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_ntohl(x) : __bpf_ntohl(x))
|
||||
#define bpf_cpu_to_be64(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_cpu_to_be64(x) : __bpf_cpu_to_be64(x))
|
||||
#define bpf_be64_to_cpu(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_be64_to_cpu(x) : __bpf_be64_to_cpu(x))
|
||||
|
||||
#endif /* __BPF_ENDIAN__ */
|
4139
component/control/kern/bpf_helper_defs.h
Normal file
4139
component/control/kern/bpf_helper_defs.h
Normal file
File diff suppressed because it is too large
Load Diff
263
component/control/kern/bpf_helpers.h
Normal file
263
component/control/kern/bpf_helpers.h
Normal file
@ -0,0 +1,263 @@
|
||||
// Copied from https://github.com/cilium/ebpf/blob/e0ada270a5/examples/headers/bpf_helpers.h
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_HELPERS__
|
||||
#define __BPF_HELPERS__
|
||||
|
||||
/*
|
||||
* Note that bpf programs need to include either
|
||||
* vmlinux.h (auto-generated from BTF) or linux/types.h
|
||||
* in advance since bpf_helper_defs.h uses such types
|
||||
* as __u64.
|
||||
*/
|
||||
#include "bpf_helper_defs.h"
|
||||
|
||||
#define __uint(name, val) int (*name)[val]
|
||||
#define __type(name, val) typeof(val) *name
|
||||
#define __array(name, val) typeof(val) *name[]
|
||||
|
||||
/*
|
||||
* Helper macro to place programs, maps, license in
|
||||
* different sections in elf_bpf file. Section names
|
||||
* are interpreted by libbpf depending on the context (BPF programs, BPF maps,
|
||||
* extern variables, etc).
|
||||
* To allow use of SEC() with externs (e.g., for extern .maps declarations),
|
||||
* make sure __attribute__((unused)) doesn't trigger compilation warning.
|
||||
*/
|
||||
#define SEC(name) \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wignored-attributes\"") \
|
||||
__attribute__((section(name), used)) \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
|
||||
/* Avoid 'linux/stddef.h' definition of '__always_inline'. */
|
||||
#undef __always_inline
|
||||
#define __always_inline inline __attribute__((always_inline))
|
||||
|
||||
#ifndef __noinline
|
||||
#define __noinline __attribute__((noinline))
|
||||
#endif
|
||||
#ifndef __weak
|
||||
#define __weak __attribute__((weak))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use __hidden attribute to mark a non-static BPF subprogram effectively
|
||||
* static for BPF verifier's verification algorithm purposes, allowing more
|
||||
* extensive and permissive BPF verification process, taking into account
|
||||
* subprogram's caller context.
|
||||
*/
|
||||
#define __hidden __attribute__((visibility("hidden")))
|
||||
|
||||
/* When utilizing vmlinux.h with BPF CO-RE, user BPF programs can't include
|
||||
* any system-level headers (such as stddef.h, linux/version.h, etc), and
|
||||
* commonly-used macros like NULL and KERNEL_VERSION aren't available through
|
||||
* vmlinux.h. This just adds unnecessary hurdles and forces users to re-define
|
||||
* them on their own. So as a convenience, provide such definitions here.
|
||||
*/
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL_VERSION
|
||||
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper macros to manipulate data structures
|
||||
*/
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((unsigned long)&((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, member) \
|
||||
({ \
|
||||
void *__mptr = (void *)(ptr); \
|
||||
((type *)(__mptr - offsetof(type, member))); \
|
||||
})
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper macro to throw a compilation error if __bpf_unreachable() gets
|
||||
* built into the resulting code. This works given BPF back end does not
|
||||
* implement __builtin_trap(). This is useful to assert that certain paths
|
||||
* of the program code are never used and hence eliminated by the compiler.
|
||||
*
|
||||
* For example, consider a switch statement that covers known cases used by
|
||||
* the program. __bpf_unreachable() can then reside in the default case. If
|
||||
* the program gets extended such that a case is not covered in the switch
|
||||
* statement, then it will throw a build error due to the default case not
|
||||
* being compiled out.
|
||||
*/
|
||||
#ifndef __bpf_unreachable
|
||||
# define __bpf_unreachable() __builtin_trap()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper function to perform a tail call with a constant/immediate map slot.
|
||||
*/
|
||||
#if __clang_major__ >= 8 && defined(__bpf__)
|
||||
static __always_inline void
|
||||
bpf_tail_call_static(void *ctx, const void *map, const __u32 slot)
|
||||
{
|
||||
if (!__builtin_constant_p(slot))
|
||||
__bpf_unreachable();
|
||||
|
||||
/*
|
||||
* Provide a hard guarantee that LLVM won't optimize setting r2 (map
|
||||
* pointer) and r3 (constant map index) from _different paths_ ending
|
||||
* up at the _same_ call insn as otherwise we won't be able to use the
|
||||
* jmpq/nopl retpoline-free patching by the x86-64 JIT in the kernel
|
||||
* given they mismatch. See also d2e4c1e6c294 ("bpf: Constant map key
|
||||
* tracking for prog array pokes") for details on verifier tracking.
|
||||
*
|
||||
* Note on clobber list: we need to stay in-line with BPF calling
|
||||
* convention, so even if we don't end up using r0, r4, r5, we need
|
||||
* to mark them as clobber so that LLVM doesn't end up using them
|
||||
* before / after the call.
|
||||
*/
|
||||
asm volatile("r1 = %[ctx]\n\t"
|
||||
"r2 = %[map]\n\t"
|
||||
"r3 = %[slot]\n\t"
|
||||
"call 12"
|
||||
:: [ctx]"r"(ctx), [map]"r"(map), [slot]"i"(slot)
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper structure used by eBPF C program
|
||||
* to describe BPF map attributes to libbpf loader
|
||||
*/
|
||||
struct bpf_map_def {
|
||||
unsigned int type;
|
||||
unsigned int key_size;
|
||||
unsigned int value_size;
|
||||
unsigned int max_entries;
|
||||
unsigned int map_flags;
|
||||
};
|
||||
|
||||
enum libbpf_pin_type {
|
||||
LIBBPF_PIN_NONE,
|
||||
/* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */
|
||||
LIBBPF_PIN_BY_NAME,
|
||||
};
|
||||
|
||||
enum libbpf_tristate {
|
||||
TRI_NO = 0,
|
||||
TRI_YES = 1,
|
||||
TRI_MODULE = 2,
|
||||
};
|
||||
|
||||
#define __kconfig __attribute__((section(".kconfig")))
|
||||
#define __ksym __attribute__((section(".ksyms")))
|
||||
|
||||
#ifndef ___bpf_concat
|
||||
#define ___bpf_concat(a, b) a ## b
|
||||
#endif
|
||||
#ifndef ___bpf_apply
|
||||
#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
|
||||
#endif
|
||||
#ifndef ___bpf_nth
|
||||
#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
|
||||
#endif
|
||||
#ifndef ___bpf_narg
|
||||
#define ___bpf_narg(...) \
|
||||
___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
#endif
|
||||
|
||||
#define ___bpf_fill0(arr, p, x) do {} while (0)
|
||||
#define ___bpf_fill1(arr, p, x) arr[p] = x
|
||||
#define ___bpf_fill2(arr, p, x, args...) arr[p] = x; ___bpf_fill1(arr, p + 1, args)
|
||||
#define ___bpf_fill3(arr, p, x, args...) arr[p] = x; ___bpf_fill2(arr, p + 1, args)
|
||||
#define ___bpf_fill4(arr, p, x, args...) arr[p] = x; ___bpf_fill3(arr, p + 1, args)
|
||||
#define ___bpf_fill5(arr, p, x, args...) arr[p] = x; ___bpf_fill4(arr, p + 1, args)
|
||||
#define ___bpf_fill6(arr, p, x, args...) arr[p] = x; ___bpf_fill5(arr, p + 1, args)
|
||||
#define ___bpf_fill7(arr, p, x, args...) arr[p] = x; ___bpf_fill6(arr, p + 1, args)
|
||||
#define ___bpf_fill8(arr, p, x, args...) arr[p] = x; ___bpf_fill7(arr, p + 1, args)
|
||||
#define ___bpf_fill9(arr, p, x, args...) arr[p] = x; ___bpf_fill8(arr, p + 1, args)
|
||||
#define ___bpf_fill10(arr, p, x, args...) arr[p] = x; ___bpf_fill9(arr, p + 1, args)
|
||||
#define ___bpf_fill11(arr, p, x, args...) arr[p] = x; ___bpf_fill10(arr, p + 1, args)
|
||||
#define ___bpf_fill12(arr, p, x, args...) arr[p] = x; ___bpf_fill11(arr, p + 1, args)
|
||||
#define ___bpf_fill(arr, args...) \
|
||||
___bpf_apply(___bpf_fill, ___bpf_narg(args))(arr, 0, args)
|
||||
|
||||
/*
|
||||
* BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values
|
||||
* in a structure.
|
||||
*/
|
||||
#define BPF_SEQ_PRINTF(seq, fmt, args...) \
|
||||
({ \
|
||||
static const char ___fmt[] = fmt; \
|
||||
unsigned long long ___param[___bpf_narg(args)]; \
|
||||
\
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
___bpf_fill(___param, args); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
\
|
||||
bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \
|
||||
___param, sizeof(___param)); \
|
||||
})
|
||||
|
||||
/*
|
||||
* BPF_SNPRINTF wraps the bpf_snprintf helper with variadic arguments instead of
|
||||
* an array of u64.
|
||||
*/
|
||||
#define BPF_SNPRINTF(out, out_size, fmt, args...) \
|
||||
({ \
|
||||
static const char ___fmt[] = fmt; \
|
||||
unsigned long long ___param[___bpf_narg(args)]; \
|
||||
\
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
___bpf_fill(___param, args); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
\
|
||||
bpf_snprintf(out, out_size, ___fmt, \
|
||||
___param, sizeof(___param)); \
|
||||
})
|
||||
|
||||
#ifdef BPF_NO_GLOBAL_DATA
|
||||
#define BPF_PRINTK_FMT_MOD
|
||||
#else
|
||||
#define BPF_PRINTK_FMT_MOD static const
|
||||
#endif
|
||||
|
||||
#define __bpf_printk(fmt, ...) \
|
||||
({ \
|
||||
BPF_PRINTK_FMT_MOD char ____fmt[] = fmt; \
|
||||
bpf_trace_printk(____fmt, sizeof(____fmt), \
|
||||
##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
/*
|
||||
* __bpf_vprintk wraps the bpf_trace_vprintk helper with variadic arguments
|
||||
* instead of an array of u64.
|
||||
*/
|
||||
#define __bpf_vprintk(fmt, args...) \
|
||||
({ \
|
||||
static const char ___fmt[] = fmt; \
|
||||
unsigned long long ___param[___bpf_narg(args)]; \
|
||||
\
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
___bpf_fill(___param, args); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
\
|
||||
bpf_trace_vprintk(___fmt, sizeof(___fmt), \
|
||||
___param, sizeof(___param)); \
|
||||
})
|
||||
|
||||
/* Use __bpf_printk when bpf_printk call has 3 or fewer fmt args
|
||||
* Otherwise use __bpf_vprintk
|
||||
*/
|
||||
#define ___bpf_pick_printk(...) \
|
||||
___bpf_nth(_, ##__VA_ARGS__, __bpf_vprintk, __bpf_vprintk, __bpf_vprintk, \
|
||||
__bpf_vprintk, __bpf_vprintk, __bpf_vprintk, __bpf_vprintk, \
|
||||
__bpf_vprintk, __bpf_vprintk, __bpf_printk /*3*/, __bpf_printk /*2*/,\
|
||||
__bpf_printk /*1*/, __bpf_printk /*0*/)
|
||||
|
||||
/* Helper macro to print out debug messages */
|
||||
#define bpf_printk(fmt, args...) ___bpf_pick_printk(args)(fmt, ##args)
|
||||
|
||||
#endif
|
@ -1,30 +1,23 @@
|
||||
// +build ignore
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2022, mzz2017 (mzz@tuta.io). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <asm-generic/errno-base.h>
|
||||
#include <iproute2/bpf_elf.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/if.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include "bpf_endian.h"
|
||||
#include "bpf_helpers.h"
|
||||
|
||||
// #include "addr.h"
|
||||
|
||||
// #define likely(x) x
|
||||
// #define unlikely(x) x
|
||||
@ -41,12 +34,15 @@
|
||||
|
||||
#define MAX_PARAM_LEN 16
|
||||
#define MAX_INTERFACE_NUM 128
|
||||
#define MAX_ROUTING_LEN 96
|
||||
#define MAX_ROUTING_LEN (32 * 3)
|
||||
#define MAX_LPM_SIZE 20480
|
||||
//#define MAX_LPM_SIZE 20480
|
||||
#define MAX_LPM_NUM (MAX_ROUTING_LEN + 8)
|
||||
#define MAX_DEST_MAPPING_NUM (65536 * 2)
|
||||
#define IPV6_MAX_EXTENSIONS 4
|
||||
|
||||
#define OUTBOUND_DIRECT 0
|
||||
#define OUTBOUND_BLOCK 1
|
||||
#define OUTBOUND_CONTROL_PLANE_DIRECT 0xFE
|
||||
#define OUTBOUND_LOGICAL_AND 0xFF
|
||||
|
||||
@ -62,10 +58,6 @@ static const __u32 zero_key = 0;
|
||||
static const __u32 tproxy_port_key = 1;
|
||||
static const __u32 disable_l4_tx_checksum_key = 2;
|
||||
static const __u32 disable_l4_rx_checksum_key = 3;
|
||||
static const __u32 epoch_key __attribute__((unused, deprecated)) = 4;
|
||||
static const __u32 routings_len_key __attribute__((unused, deprecated)) = 5;
|
||||
|
||||
static __be32 unspecific_ipv6[4] __attribute__((__unused__)) = {0, 0, 0, 0};
|
||||
|
||||
struct ip_port {
|
||||
__be32 ip[4];
|
||||
@ -96,7 +88,7 @@ struct {
|
||||
// enough for identifier. And UDP client
|
||||
// side does not care it (full-cone).
|
||||
__type(value, struct ip_port_outbound); // Original target.
|
||||
__uint(max_entries, 0xFF << 2);
|
||||
__uint(max_entries, MAX_DEST_MAPPING_NUM);
|
||||
/// NOTICE: It MUST be pinned.
|
||||
__uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
} dst_map SEC(".maps");
|
||||
@ -132,7 +124,7 @@ struct {
|
||||
__uint(max_entries, MAX_INTERFACE_NUM);
|
||||
/// NOTICE: No persistence.
|
||||
// __uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
} ifindex_ip_map SEC(".maps");
|
||||
} ifindex_tproxy_ip_map SEC(".maps");
|
||||
|
||||
// Array of LPM tries:
|
||||
struct lpm_key {
|
||||
@ -145,12 +137,12 @@ struct map_lpm_type {
|
||||
__uint(max_entries, MAX_LPM_SIZE);
|
||||
__uint(key_size, sizeof(struct lpm_key));
|
||||
__uint(value_size, sizeof(__u32));
|
||||
} unused_lpm_type SEC(".maps");
|
||||
} unused_lpm_type SEC(".maps"), host_ip_lpm SEC(".maps");
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
|
||||
__uint(key_size, sizeof(__u32));
|
||||
__uint(max_entries, MAX_LPM_NUM);
|
||||
__uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
// __uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
__array(values, struct map_lpm_type);
|
||||
} lpm_array_map SEC(".maps");
|
||||
|
||||
@ -199,16 +191,11 @@ struct {
|
||||
__type(key, __u32);
|
||||
__type(value, struct routing);
|
||||
__uint(max_entries, MAX_ROUTING_LEN);
|
||||
__uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
// __uint(pinning, LIBBPF_PIN_BY_NAME);
|
||||
} routing_map SEC(".maps");
|
||||
|
||||
struct domain_routing {
|
||||
__u32 bitmap[MAX_ROUTING_LEN / 32];
|
||||
/// DEPRECATED: Epoch is the epoch at the write time. Every time the control
|
||||
/// plane restarts, epoch += 1. It was deprecated because long connection will
|
||||
/// keep their states by persistent dst_map (we only need to know if it is a
|
||||
/// old connection).
|
||||
__u32 epoch;
|
||||
};
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_LRU_HASH);
|
||||
@ -220,7 +207,7 @@ struct {
|
||||
|
||||
// Functions:
|
||||
|
||||
static __always_inline bool equal_ipv6(__be32 x[4], __be32 y[4]) {
|
||||
static __always_inline bool equal_ipv6_format(__be32 x[4], __be32 y[4]) {
|
||||
#if __clang_major__ >= 10
|
||||
return ((__be64 *)x)[0] == ((__be64 *)y)[0] &&
|
||||
((__be64 *)x)[1] == ((__be64 *)y)[1];
|
||||
@ -248,7 +235,7 @@ static __always_inline long rewrite_ip(struct __sk_buff *skb, bool is_ipv6,
|
||||
__u8 proto, __u8 ihl, __be32 old_ip[4],
|
||||
__be32 new_ip[4], bool is_dest) {
|
||||
// Nothing to do.
|
||||
if (equal_ipv6(old_ip, new_ip)) {
|
||||
if (equal_ipv6_format(old_ip, new_ip)) {
|
||||
return 0;
|
||||
}
|
||||
// bpf_printk("%pI6->%pI6", old_ip, new_ip);
|
||||
@ -486,28 +473,26 @@ parse_transport(struct __sk_buff *skb, struct ethhdr **ethh, struct iphdr **iph,
|
||||
}
|
||||
|
||||
static __always_inline long ip_is_host(bool is_ipv6, __u32 ifindex,
|
||||
__be32 ip[4],
|
||||
__be32 (*first_interface_ip)[4]) {
|
||||
struct if_ip *if_ip = bpf_map_lookup_elem(&ifindex_ip_map, &ifindex);
|
||||
if (unlikely(!if_ip)) {
|
||||
return -1;
|
||||
__be32 ip[4], __be32 tproxy_ip[4]) {
|
||||
if (tproxy_ip) {
|
||||
struct if_ip *if_ip = bpf_map_lookup_elem(&ifindex_tproxy_ip_map, &ifindex);
|
||||
if (unlikely(!if_ip)) {
|
||||
return -1;
|
||||
}
|
||||
if (!is_ipv6 && (*if_ip).hasIp4) {
|
||||
__builtin_memcpy(tproxy_ip, (*if_ip).ip4, IPV6_BYTE_LENGTH);
|
||||
} else if (is_ipv6 && (*if_ip).hasIp6) {
|
||||
__builtin_memcpy(tproxy_ip, (*if_ip).ip6, IPV6_BYTE_LENGTH);
|
||||
} else {
|
||||
// Should TC_ACT_OK outer.
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
__u32 host_ip[4];
|
||||
if (!is_ipv6 && (*if_ip).hasIp4) {
|
||||
__builtin_memcpy(host_ip, (*if_ip).ip4, IPV6_BYTE_LENGTH);
|
||||
} else if (is_ipv6 && (*if_ip).hasIp6) {
|
||||
__builtin_memcpy(host_ip, (*if_ip).ip6, IPV6_BYTE_LENGTH);
|
||||
} else {
|
||||
// Should TC_ACT_OK outer.
|
||||
return -EFAULT;
|
||||
}
|
||||
if (first_interface_ip) {
|
||||
__builtin_memcpy(*first_interface_ip, host_ip, IPV6_BYTE_LENGTH);
|
||||
}
|
||||
if (equal_ipv6(ip, host_ip)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
struct lpm_key lpm_key;
|
||||
lpm_key.trie_key.prefixlen = IPV6_BYTE_LENGTH * 8;
|
||||
__builtin_memcpy(lpm_key.data, ip, IPV6_BYTE_LENGTH);
|
||||
return bpf_map_lookup_elem(&host_ip_lpm, &lpm_key) ? 1 : 0;
|
||||
}
|
||||
|
||||
static __always_inline long adjust_udp_len(struct __sk_buff *skb, __u16 oldlen,
|
||||
@ -597,9 +582,9 @@ static __always_inline long encap_after_udp_hdr(struct __sk_buff *skb,
|
||||
__be16 iphdr_tot_len,
|
||||
void *newhdr, __u32 newhdrlen) {
|
||||
if (unlikely(newhdrlen % 4 != 0)) {
|
||||
bpf_trace_printk("encap_after_udp_hdr: unexpected newhdrlen value %u :must "
|
||||
"be a multiple of 4",
|
||||
newhdrlen);
|
||||
bpf_printk("encap_after_udp_hdr: unexpected newhdrlen value %u :must "
|
||||
"be a multiple of 4",
|
||||
newhdrlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -664,10 +649,9 @@ static __always_inline int decap_after_udp_hdr(struct __sk_buff *skb,
|
||||
__be16 iphdr_tot_len, void *to,
|
||||
__u32 decap_hdrlen) {
|
||||
if (unlikely(decap_hdrlen % 4 != 0)) {
|
||||
bpf_trace_printk(
|
||||
"encap_after_udp_hdr: unexpected decap_hdrlen value %u :must "
|
||||
"be a multiple of 4",
|
||||
decap_hdrlen);
|
||||
bpf_printk("encap_after_udp_hdr: unexpected decap_hdrlen value %u :must "
|
||||
"be a multiple of 4",
|
||||
decap_hdrlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
long ret = 0;
|
||||
@ -742,15 +726,7 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
||||
__be32 daddr[4], __be32 mac[4]) {
|
||||
#define _l4proto flag[0]
|
||||
#define _ipversion flag[1]
|
||||
// // Get len of routings and epoch from param_map.
|
||||
// __u32 *routings_len = bpf_map_lookup_elem(¶m_map, &routings_len_key);
|
||||
// if (!routings_len) {
|
||||
// return -EINVAL;
|
||||
// }
|
||||
// __u32 *epoch = bpf_map_lookup_elem(¶m_map, &epoch_key);
|
||||
// if (!epoch) {
|
||||
// return -EINVAL;
|
||||
// }
|
||||
|
||||
// Define variables for further use.
|
||||
__u16 h_dport;
|
||||
__u16 h_sport;
|
||||
@ -786,13 +762,6 @@ static long routing(__u8 flag[2], void *l4_hdr, __be32 saddr[4],
|
||||
bool bad_rule = false;
|
||||
struct domain_routing *domain_routing;
|
||||
|
||||
/// DEPRECATED: Epoch was deprecated and domain_routing_map was unpinned, thus
|
||||
/// this branch will never hit.
|
||||
// if (domain_routing && domain_routing->epoch != *epoch) {
|
||||
// // Dirty (epoch dismatch) traffic should be routed by the control plane.
|
||||
// return OUTBOUND_CONTROL_PLANE_DIRECT;
|
||||
// }
|
||||
|
||||
#pragma unroll
|
||||
for (__u32 key = 0; key < MAX_ROUTING_LEN; key++) {
|
||||
__u32 k = key; // Clone to pass code checker.
|
||||
@ -895,6 +864,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
struct udphdr *udph;
|
||||
__sum16 bak_cksm;
|
||||
__u8 ihl;
|
||||
bool tcp_state_syn;
|
||||
long ret = parse_transport(skb, ðh, &iph, &ipv6h, &tcph, &udph, &ihl);
|
||||
if (ret) {
|
||||
bpf_printk("parse_transport: %ld", ret);
|
||||
@ -906,13 +876,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
|
||||
// Backup for further use.
|
||||
__u8 l4_proto;
|
||||
if (tcph) {
|
||||
l4_proto = IPPROTO_TCP;
|
||||
} else if (udph) {
|
||||
l4_proto = IPPROTO_UDP;
|
||||
} else {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
__be16 ip_tot_len = 0;
|
||||
|
||||
// Parse saddr and daddr as ipv6 format.
|
||||
__be32 saddr[4];
|
||||
@ -927,6 +891,8 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
daddr[1] = 0;
|
||||
daddr[2] = bpf_htonl(0x0000ffff);
|
||||
daddr[3] = iph->daddr;
|
||||
|
||||
ip_tot_len = iph->tot_len;
|
||||
} else if (ipv6h) {
|
||||
__builtin_memcpy(daddr, &ipv6h->daddr, IPV6_BYTE_LENGTH);
|
||||
__builtin_memcpy(saddr, &ipv6h->saddr, IPV6_BYTE_LENGTH);
|
||||
@ -935,8 +901,8 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
}
|
||||
|
||||
// If this packet is sent to this host, accept it.
|
||||
__u32 first_interface_ip[4];
|
||||
long to_host = ip_is_host(ipv6h, skb->ifindex, daddr, &first_interface_ip);
|
||||
__u32 tproxy_ip[4];
|
||||
long to_host = ip_is_host(ipv6h, skb->ifindex, daddr, tproxy_ip);
|
||||
if (to_host < 0) { // error
|
||||
// bpf_printk("to_host: %ld", to_host);
|
||||
return TC_ACT_OK;
|
||||
@ -946,7 +912,6 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
// To host:53. Process it.
|
||||
} else {
|
||||
// To host. Accept.
|
||||
/// FIXME: all host ip.
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
}
|
||||
@ -958,8 +923,9 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
|
||||
if (tcph) {
|
||||
// Backup for further use.
|
||||
l4_proto = IPPROTO_TCP;
|
||||
bak_cksm = tcph->check;
|
||||
bool tcp_state_syn = tcph->syn && !tcph->ack;
|
||||
tcp_state_syn = tcph->syn && !tcph->ack;
|
||||
struct ip_port_proto key_src;
|
||||
__builtin_memset(&key_src, 0, sizeof(key_src));
|
||||
__builtin_memcpy(key_src.ip, saddr, IPV6_BYTE_LENGTH);
|
||||
@ -1003,6 +969,8 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
bpf_printk("tcp: outbound: %u, %pI6", outbound, daddr);
|
||||
if (outbound == OUTBOUND_DIRECT) {
|
||||
return TC_ACT_OK;
|
||||
} else if (unlikely(outbound == OUTBOUND_BLOCK)) {
|
||||
return TC_ACT_SHOT;
|
||||
} else {
|
||||
// Rewrite to control plane.
|
||||
|
||||
@ -1017,8 +985,8 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
|
||||
__u32 *dst_ip = daddr;
|
||||
__u16 dst_port = tcph->dest;
|
||||
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_TCP, ihl, dst_ip,
|
||||
first_interface_ip, true))) {
|
||||
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_TCP, ihl, dst_ip, tproxy_ip,
|
||||
true))) {
|
||||
bpf_printk("Shot IP: %ld", ret);
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
@ -1031,6 +999,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
} else if (udph) {
|
||||
// Backup for further use.
|
||||
bak_cksm = udph->check;
|
||||
l4_proto = IPPROTO_UDP;
|
||||
struct ip_port_outbound new_hdr;
|
||||
__builtin_memset(&new_hdr, 0, sizeof(new_hdr));
|
||||
__builtin_memcpy(new_hdr.ip, daddr, IPV6_BYTE_LENGTH);
|
||||
@ -1059,18 +1028,19 @@ int tproxy_ingress(struct __sk_buff *skb) {
|
||||
|
||||
if (new_hdr.outbound == OUTBOUND_DIRECT) {
|
||||
return TC_ACT_OK;
|
||||
} else if (unlikely(new_hdr.outbound == OUTBOUND_BLOCK)) {
|
||||
return TC_ACT_SHOT;
|
||||
} else {
|
||||
// Rewrite to control plane.
|
||||
|
||||
// Encap a header to transmit fullcone tuple.
|
||||
__be16 ip_tot_len = iph ? iph->tot_len : 0;
|
||||
encap_after_udp_hdr(skb, ipv6h, ihl, ip_tot_len, &new_hdr,
|
||||
sizeof(new_hdr));
|
||||
|
||||
// Rewrite udp dst ip.
|
||||
// bpf_printk("rewrite dst ip from %pI4", &ori_dst.ip);
|
||||
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_UDP, ihl, new_hdr.ip,
|
||||
first_interface_ip, true))) {
|
||||
if ((ret = rewrite_ip(skb, ipv6h, IPPROTO_UDP, ihl, new_hdr.ip, tproxy_ip,
|
||||
true))) {
|
||||
bpf_printk("Shot IP: %ld", ret);
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
@ -1129,6 +1099,7 @@ int tproxy_egress(struct __sk_buff *skb) {
|
||||
struct tcphdr *tcph;
|
||||
struct udphdr *udph;
|
||||
__sum16 bak_cksm;
|
||||
__u8 l4_proto;
|
||||
__u8 ihl;
|
||||
long ret = parse_transport(skb, ðh, &iph, &ipv6h, &tcph, &udph, &ihl);
|
||||
if (ret) {
|
||||
@ -1138,6 +1109,7 @@ int tproxy_egress(struct __sk_buff *skb) {
|
||||
// Parse saddr and daddr as ipv6 format.
|
||||
__be32 saddr[4];
|
||||
__be32 daddr[4];
|
||||
__be16 ip_tot_len = 0;
|
||||
if (iph) {
|
||||
saddr[0] = 0;
|
||||
saddr[1] = 0;
|
||||
@ -1148,6 +1120,8 @@ int tproxy_egress(struct __sk_buff *skb) {
|
||||
daddr[1] = 0;
|
||||
daddr[2] = bpf_htonl(0x0000ffff);
|
||||
daddr[3] = iph->daddr;
|
||||
|
||||
ip_tot_len = iph->tot_len;
|
||||
} else if (ipv6h) {
|
||||
__builtin_memcpy(daddr, ipv6h->daddr.in6_u.u6_addr32, IPV6_BYTE_LENGTH);
|
||||
__builtin_memcpy(saddr, ipv6h->saddr.in6_u.u6_addr32, IPV6_BYTE_LENGTH);
|
||||
@ -1160,23 +1134,17 @@ int tproxy_egress(struct __sk_buff *skb) {
|
||||
if (!tproxy_port) {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
long from_host = ip_is_host(ipv6h, skb->ifindex, saddr, NULL);
|
||||
if (!(from_host == 1)) {
|
||||
// Not from localhost.
|
||||
__be32 tproxy_ip[4];
|
||||
ret = ip_is_host(ipv6h, skb->ifindex, saddr, tproxy_ip);
|
||||
if (!(ret == 1)) {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
if (!equal_ipv6_format(saddr, tproxy_ip)) {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
// Backup for further use.
|
||||
__u8 l4_proto;
|
||||
if (tcph) {
|
||||
l4_proto = IPPROTO_TCP;
|
||||
} else if (udph) {
|
||||
l4_proto = IPPROTO_UDP;
|
||||
} else {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
if (tcph) {
|
||||
if (tcph->source != *tproxy_port) {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
@ -1216,6 +1184,7 @@ int tproxy_egress(struct __sk_buff *skb) {
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
} else if (udph) {
|
||||
l4_proto = IPPROTO_UDP;
|
||||
if (udph->source != *tproxy_port) {
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
@ -1233,7 +1202,6 @@ int tproxy_egress(struct __sk_buff *skb) {
|
||||
// Get source ip/port from our packet header.
|
||||
|
||||
// Decap header to get fullcone tuple.
|
||||
__be16 ip_tot_len = iph ? iph->tot_len : 0;
|
||||
decap_after_udp_hdr(skb, ipv6h, ihl, ip_tot_len, &ori_src, sizeof(ori_src));
|
||||
|
||||
// Rewrite udp src ip
|
||||
@ -1274,7 +1242,7 @@ int tproxy_egress(struct __sk_buff *skb) {
|
||||
if (*disable_l4_checksum == DISABLE_L4_CHECKSUM_POLICY_SET_ZERO) {
|
||||
bak_cksm = 0;
|
||||
}
|
||||
bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, 2, 0);
|
||||
bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0);
|
||||
}
|
||||
}
|
||||
return TC_ACT_OK;
|
||||
|
@ -20,6 +20,7 @@ type DomainSet struct {
|
||||
RuleIndex int
|
||||
Domains []string
|
||||
}
|
||||
|
||||
type RoutingMatcherBuilder struct {
|
||||
*routing.DefaultMatcherBuilder
|
||||
outboundName2Id map[string]uint8
|
||||
@ -74,7 +75,7 @@ func (b *RoutingMatcherBuilder) AddDomain(key string, values []string, outbound
|
||||
})
|
||||
}
|
||||
|
||||
func (b *RoutingMatcherBuilder) AddMac(macAddrs [][6]byte, outbound string) {
|
||||
func (b *RoutingMatcherBuilder) AddSourceMac(macAddrs [][6]byte, outbound string) {
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
@ -108,7 +109,7 @@ func (b *RoutingMatcherBuilder) AddIp(values []netip.Prefix, outbound string) {
|
||||
})
|
||||
}
|
||||
|
||||
func (b *RoutingMatcherBuilder) AddSource(values []netip.Prefix, outbound string) {
|
||||
func (b *RoutingMatcherBuilder) AddSourceIp(values []netip.Prefix, outbound string) {
|
||||
if b.err != nil {
|
||||
return
|
||||
}
|
||||
@ -166,9 +167,9 @@ func (b *RoutingMatcherBuilder) Build() (err error) {
|
||||
keys = append(keys, cidrToBpfLpmKey(cidr))
|
||||
values = append(values, 1)
|
||||
}
|
||||
m, err := b.bpf.NewLpmMap(keys, values)
|
||||
m, err := b.bpf.newLpmMap(keys, values)
|
||||
if err != nil {
|
||||
return fmt.Errorf("NewLpmMap: %w", err)
|
||||
return fmt.Errorf("newLpmMap: %w", err)
|
||||
}
|
||||
// ebpf.Map cannot be BatchUpdate
|
||||
if err = b.bpf.LpmArrayMap.Update(uint32(i), m, ebpf.UpdateAny); err != nil {
|
||||
@ -177,7 +178,12 @@ func (b *RoutingMatcherBuilder) Build() (err error) {
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
// Update routings.
|
||||
// Write routings.
|
||||
// Final rule MUST be the last.
|
||||
if b.rules[len(b.rules)-1].Type != uint8(consts.RoutingType_Final) {
|
||||
b.err = fmt.Errorf("final rule MUST be the last")
|
||||
return b.err
|
||||
}
|
||||
routingsLen := uint32(len(b.rules))
|
||||
routingsKeys := common.ARangeU32(routingsLen)
|
||||
if _, err = b.bpf.RoutingMap.BatchUpdate(routingsKeys, b.rules, &ebpf.BatchOptions{
|
||||
@ -185,8 +191,5 @@ func (b *RoutingMatcherBuilder) Build() (err error) {
|
||||
}); err != nil {
|
||||
return fmt.Errorf("BatchUpdate: %w", err)
|
||||
}
|
||||
if err = b.bpf.ParamMap.Update(consts.RoutingsLenKey, routingsLen, ebpf.UpdateAny); err != nil {
|
||||
return fmt.Errorf("Update: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
21
component/outbound/dialer/block.go
Normal file
21
component/outbound/dialer/block.go
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2023, mzz2017 (mzz@tuta.io). All rights reserved.
|
||||
*/
|
||||
|
||||
package dialer
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"net"
|
||||
)
|
||||
|
||||
type blockDialer struct{}
|
||||
|
||||
func (*blockDialer) Dial(network string, addr string) (c net.Conn, err error) {
|
||||
return nil, net.ErrClosed
|
||||
}
|
||||
|
||||
func NewBlockDialer(log *logrus.Logger) *Dialer {
|
||||
return newDialer(&blockDialer{}, log, true, "block", "block", "")
|
||||
}
|
@ -24,6 +24,8 @@ var (
|
||||
)
|
||||
|
||||
type Dialer struct {
|
||||
log *logrus.Logger
|
||||
|
||||
proxy.Dialer
|
||||
supportUDP bool
|
||||
name string
|
||||
@ -40,16 +42,17 @@ type Dialer struct {
|
||||
}
|
||||
|
||||
// NewDialer is for register in general.
|
||||
func NewDialer(dialer proxy.Dialer, supportUDP bool, name string, protocol string, link string) *Dialer {
|
||||
d := newDialer(dialer, supportUDP, name, protocol, link)
|
||||
func NewDialer(dialer proxy.Dialer, log *logrus.Logger, supportUDP bool, name string, protocol string, link string) *Dialer {
|
||||
d := newDialer(dialer, log, supportUDP, name, protocol, link)
|
||||
go d.aliveBackground()
|
||||
return d
|
||||
}
|
||||
|
||||
// newDialer does not run background tasks.
|
||||
func newDialer(dialer proxy.Dialer, supportUDP bool, name string, protocol string, link string) *Dialer {
|
||||
func newDialer(dialer proxy.Dialer, log *logrus.Logger, supportUDP bool, name string, protocol string, link string) *Dialer {
|
||||
d := &Dialer{
|
||||
Dialer: dialer,
|
||||
log: log,
|
||||
supportUDP: supportUDP,
|
||||
name: name,
|
||||
protocol: protocol,
|
||||
@ -132,13 +135,13 @@ func (d *Dialer) Test(timeout time.Duration, url string) (ok bool, err error) {
|
||||
// No error.
|
||||
latency := time.Since(start)
|
||||
// FIXME: Use log instead of logrus.
|
||||
logrus.Debugf("Connectivity Test <%v>: %v", d.name, latency)
|
||||
d.log.Debugf("Connectivity Test <%v>: %v", d.name, latency)
|
||||
d.Latencies10.AppendLatency(latency)
|
||||
alive = true
|
||||
} else {
|
||||
// Append timeout if there is any error or unexpected status code.
|
||||
if err != nil {
|
||||
logrus.Debugf("Connectivity Test <%v>: %v", d.name, err.Error())
|
||||
d.log.Debugf("Connectivity Test <%v>: %v", d.name, err.Error())
|
||||
}
|
||||
d.Latencies10.AppendLatency(timeout)
|
||||
}
|
||||
|
@ -1,15 +1,21 @@
|
||||
package dialer
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/proxy"
|
||||
"net"
|
||||
)
|
||||
|
||||
var SymmetricDirect = NewDirect(false)
|
||||
var FullconeDirect = NewDirect(true)
|
||||
var SymmetricDirect = newDirect(false)
|
||||
var FullconeDirect = newDirect(true)
|
||||
|
||||
var SymmetricDirectDialer = newDialer(SymmetricDirect, true, "direct", "direct", "")
|
||||
var FullconeDirectDialer = newDialer(FullconeDirect, true, "direct", "direct", "")
|
||||
func NewDirectDialer(log *logrus.Logger, fullcone bool) *Dialer {
|
||||
if fullcone {
|
||||
return newDialer(FullconeDirect, log, true, "direct", "direct", "")
|
||||
} else {
|
||||
return newDialer(SymmetricDirect, log, true, "direct", "direct", "")
|
||||
}
|
||||
}
|
||||
|
||||
type direct struct {
|
||||
proxy.Dialer
|
||||
@ -17,7 +23,7 @@ type direct struct {
|
||||
fullCone bool
|
||||
}
|
||||
|
||||
func NewDirect(fullCone bool) proxy.Dialer {
|
||||
func newDirect(fullCone bool) proxy.Dialer {
|
||||
return &direct{
|
||||
netDialer: net.Dialer{},
|
||||
fullCone: fullCone,
|
||||
|
@ -2,9 +2,9 @@ package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/mzz2017/softwind/protocol/http"
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -13,7 +13,6 @@ import (
|
||||
func init() {
|
||||
dialer.FromLinkRegister("http", NewHTTP)
|
||||
dialer.FromLinkRegister("https", NewHTTP)
|
||||
dialer.FromClashRegister("http", NewSocks5FromClashObj)
|
||||
}
|
||||
|
||||
type HTTP struct {
|
||||
@ -26,20 +25,12 @@ type HTTP struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewHTTP(link string) (*dialer.Dialer, error) {
|
||||
func NewHTTP(log *logrus.Logger, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseHTTPURL(link)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", dialer.InvalidParameterErr, err)
|
||||
}
|
||||
return s.Dialer()
|
||||
}
|
||||
|
||||
func NewSocks5FromClashObj(o *yaml.Node) (*dialer.Dialer, error) {
|
||||
s, err := ParseClash(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer()
|
||||
return s.Dialer(log)
|
||||
}
|
||||
|
||||
func ParseHTTPURL(link string) (data *HTTP, err error) {
|
||||
@ -71,46 +62,13 @@ func ParseHTTPURL(link string) (data *HTTP, err error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseClash(o *yaml.Node) (data *HTTP, err error) {
|
||||
type HttpOption struct {
|
||||
Name string `yaml:"name"`
|
||||
Server string `yaml:"server"`
|
||||
Port int `yaml:"port"`
|
||||
UserName string `yaml:"username,omitempty"`
|
||||
Password string `yaml:"password,omitempty"`
|
||||
TLS bool `yaml:"tls,omitempty"`
|
||||
SNI string `yaml:"sni,omitempty"`
|
||||
SkipCertVerify bool `yaml:"skip-cert-verify,omitempty"`
|
||||
}
|
||||
var option HttpOption
|
||||
if err = o.Decode(&option); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scheme := "http"
|
||||
if option.TLS {
|
||||
scheme = "https"
|
||||
}
|
||||
if option.SkipCertVerify {
|
||||
return nil, fmt.Errorf("%w: skip-cert-verify=true", dialer.UnexpectedFieldErr)
|
||||
}
|
||||
return &HTTP{
|
||||
Name: option.Name,
|
||||
Server: option.Server,
|
||||
Port: option.Port,
|
||||
Username: option.UserName,
|
||||
Password: option.Password,
|
||||
SNI: option.SNI,
|
||||
Protocol: scheme,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *HTTP) Dialer() (*dialer.Dialer, error) {
|
||||
func (s *HTTP) Dialer(log *logrus.Logger) (*dialer.Dialer, error) {
|
||||
u := s.URL()
|
||||
d, err := http.NewHTTPProxy(&u, dialer.SymmetricDirect)
|
||||
d, err := http.NewHTTPProxy(&u, dialer.SymmetricDirect) // HTTP Proxy does not support full-cone.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, false, s.Name, s.Protocol, u.String()), nil
|
||||
return dialer.NewDialer(d, log, false, s.Name, s.Protocol, u.String()), nil
|
||||
}
|
||||
|
||||
func (s *HTTP) URL() url.URL {
|
||||
|
@ -7,11 +7,11 @@ package dialer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type FromLinkCreator func(link string) (dialer *Dialer, err error)
|
||||
type FromLinkCreator func(log *logrus.Logger, link string) (dialer *Dialer, err error)
|
||||
|
||||
var fromLinkCreators = make(map[string]FromLinkCreator)
|
||||
|
||||
@ -19,35 +19,14 @@ func FromLinkRegister(name string, creator FromLinkCreator) {
|
||||
fromLinkCreators[name] = creator
|
||||
}
|
||||
|
||||
func NewFromLink(link string) (dialer *Dialer, err error) {
|
||||
func NewFromLink(log *logrus.Logger, link string) (dialer *Dialer, err error) {
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if creator, ok := fromLinkCreators[u.Scheme]; ok {
|
||||
return creator(link)
|
||||
return creator(log, link)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unexpected link type: %v", u.Scheme)
|
||||
}
|
||||
}
|
||||
|
||||
type FromClashCreator func(clashObj *yaml.Node) (dialer *Dialer, err error)
|
||||
|
||||
var fromClashCreators = make(map[string]FromClashCreator)
|
||||
|
||||
func FromClashRegister(name string, creator FromClashCreator) {
|
||||
fromClashCreators[name] = creator
|
||||
}
|
||||
|
||||
func NewFromClash(clashObj *yaml.Node) (dialer *Dialer, err error) {
|
||||
preUnload := make(map[string]interface{})
|
||||
if err := clashObj.Decode(&preUnload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name, _ := preUnload["type"].(string)
|
||||
if creator, ok := fromClashCreators[name]; ok {
|
||||
return creator(clashObj)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unexpected link type: %v", name)
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,12 @@ package shadowsocks
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer/transport/simpleobfs"
|
||||
"github.com/mzz2017/softwind/protocol"
|
||||
"github.com/mzz2017/softwind/protocol/shadowsocks"
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/component/outbound/transport/simpleobfs"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -21,7 +21,6 @@ func init() {
|
||||
|
||||
dialer.FromLinkRegister("shadowsocks", NewShadowsocksFromLink)
|
||||
dialer.FromLinkRegister("ss", NewShadowsocksFromLink)
|
||||
dialer.FromClashRegister("ss", NewShadowsocksFromClashObj)
|
||||
}
|
||||
|
||||
type Shadowsocks struct {
|
||||
@ -35,23 +34,15 @@ type Shadowsocks struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewShadowsocksFromLink(link string) (*dialer.Dialer, error) {
|
||||
func NewShadowsocksFromLink(log *logrus.Logger, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseSSURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer()
|
||||
return s.Dialer(log)
|
||||
}
|
||||
|
||||
func NewShadowsocksFromClashObj(o *yaml.Node) (*dialer.Dialer, error) {
|
||||
s, err := ParseClash(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer()
|
||||
}
|
||||
|
||||
func (s *Shadowsocks) Dialer() (*dialer.Dialer, error) {
|
||||
func (s *Shadowsocks) Dialer(log *logrus.Logger) (*dialer.Dialer, error) {
|
||||
// FIXME: support plain/none.
|
||||
switch s.Cipher {
|
||||
case "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305":
|
||||
@ -59,7 +50,7 @@ func (s *Shadowsocks) Dialer() (*dialer.Dialer, error) {
|
||||
return nil, fmt.Errorf("unsupported shadowsocks encryption method: %v", s.Cipher)
|
||||
}
|
||||
supportUDP := s.UDP
|
||||
d := dialer.SymmetricDirect
|
||||
d := dialer.FullconeDirect // Shadowsocks Proxy supports full-cone.
|
||||
d, err := protocol.NewDialer("shadowsocks", d, protocol.Header{
|
||||
ProxyAddress: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
Cipher: s.Cipher,
|
||||
@ -86,46 +77,7 @@ func (s *Shadowsocks) Dialer() (*dialer.Dialer, error) {
|
||||
}
|
||||
supportUDP = false
|
||||
}
|
||||
return dialer.NewDialer(d, supportUDP, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseClash(o *yaml.Node) (data *Shadowsocks, err error) {
|
||||
type simpleObfsOption struct {
|
||||
Mode string `obfs:"mode,omitempty"`
|
||||
Host string `obfs:"host,omitempty"`
|
||||
}
|
||||
type ShadowSocksOption struct {
|
||||
Name string `yaml:"name"`
|
||||
Server string `yaml:"server"`
|
||||
Port int `yaml:"port"`
|
||||
Password string `yaml:"password"`
|
||||
Cipher string `yaml:"cipher"`
|
||||
UDP bool `yaml:"udp,omitempty"`
|
||||
Plugin string `yaml:"plugin,omitempty"`
|
||||
PluginOpts simpleObfsOption `yaml:"plugin-opts,omitempty"`
|
||||
}
|
||||
var option ShadowSocksOption
|
||||
if err = o.Decode(&option); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = &Shadowsocks{
|
||||
Name: option.Name,
|
||||
Server: option.Server,
|
||||
Port: option.Port,
|
||||
Password: option.Password,
|
||||
Cipher: option.Cipher,
|
||||
UDP: option.UDP,
|
||||
Protocol: "shadowsocks",
|
||||
}
|
||||
if option.Plugin == "obfs" {
|
||||
data.Plugin.Name = "simple-obfs"
|
||||
data.Plugin.Opts.Obfs = option.PluginOpts.Mode
|
||||
data.Plugin.Opts.Host = data.Plugin.Opts.Host
|
||||
if data.Plugin.Opts.Host == "" {
|
||||
data.Plugin.Opts.Host = "bing.com"
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
return dialer.NewDialer(d, log, supportUDP, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseSSURL(u string) (data *Shadowsocks, err error) {
|
||||
|
@ -3,10 +3,10 @@ package shadowsocksr
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
ssr "github.com/v2rayA/shadowsocksR/client"
|
||||
"gopkg.in/yaml.v3"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -16,7 +16,6 @@ import (
|
||||
func init() {
|
||||
dialer.FromLinkRegister("shadowsocksr", NewShadowsocksR)
|
||||
dialer.FromLinkRegister("ssr", NewShadowsocksR)
|
||||
dialer.FromClashRegister("ssr", NewShadowsocksRFromClashObj)
|
||||
}
|
||||
|
||||
type ShadowsocksR struct {
|
||||
@ -32,23 +31,15 @@ type ShadowsocksR struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewShadowsocksR(link string) (*dialer.Dialer, error) {
|
||||
func NewShadowsocksR(log *logrus.Logger, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseSSRURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer()
|
||||
return s.Dialer(log)
|
||||
}
|
||||
|
||||
func NewShadowsocksRFromClashObj(o *yaml.Node) (*dialer.Dialer, error) {
|
||||
s, err := ParseClash(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer()
|
||||
}
|
||||
|
||||
func (s *ShadowsocksR) Dialer() (*dialer.Dialer, error) {
|
||||
func (s *ShadowsocksR) Dialer(log *logrus.Logger) (*dialer.Dialer, error) {
|
||||
u := url.URL{
|
||||
Scheme: "ssr",
|
||||
User: url.UserPassword(s.Cipher, s.Password),
|
||||
@ -60,42 +51,11 @@ func (s *ShadowsocksR) Dialer() (*dialer.Dialer, error) {
|
||||
"obfs_param": []string{s.ObfsParam},
|
||||
}.Encode(),
|
||||
}
|
||||
d, err := ssr.NewSSR(u.String(), dialer.SymmetricDirect, nil)
|
||||
d, err := ssr.NewSSR(u.String(), dialer.SymmetricDirect, nil) // SSR Proxy does not support full-cone.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, false, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseClash(o *yaml.Node) (data *ShadowsocksR, err error) {
|
||||
type ShadowSocksROption struct {
|
||||
Name string `yaml:"name"`
|
||||
Server string `yaml:"server"`
|
||||
Port int `yaml:"port"`
|
||||
Password string `yaml:"password"`
|
||||
Cipher string `yaml:"cipher"`
|
||||
Obfs string `yaml:"obfs"`
|
||||
ObfsParam string `yaml:"obfs-param,omitempty"`
|
||||
Protocol string `yaml:"protocol"`
|
||||
ProtocolParam string `yaml:"protocol-param,omitempty"`
|
||||
UDP bool `yaml:"udp,omitempty"`
|
||||
}
|
||||
var option ShadowSocksROption
|
||||
if err = o.Decode(&option); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ShadowsocksR{
|
||||
Name: option.Name,
|
||||
Server: option.Server,
|
||||
Port: option.Port,
|
||||
Password: option.Password,
|
||||
Cipher: option.Cipher,
|
||||
Proto: option.Protocol,
|
||||
ProtoParam: option.ProtocolParam,
|
||||
Obfs: option.Obfs,
|
||||
ObfsParam: option.ObfsParam,
|
||||
Protocol: "shadowsocksr",
|
||||
}, nil
|
||||
return dialer.NewDialer(d, log, false, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseSSRURL(u string) (data *ShadowsocksR, err error) {
|
||||
|
@ -2,10 +2,10 @@ package socks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
//"github.com/mzz2017/softwind/protocol/socks4"
|
||||
"github.com/mzz2017/softwind/protocol/socks5"
|
||||
"gopkg.in/yaml.v3"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -16,7 +16,6 @@ func init() {
|
||||
//dialer.FromLinkRegister("socks4", NewSocks)
|
||||
//dialer.FromLinkRegister("socks4a", NewSocks)
|
||||
dialer.FromLinkRegister("socks5", NewSocks)
|
||||
dialer.FromClashRegister("socks5", NewSocks5FromClashObj)
|
||||
}
|
||||
|
||||
type Socks struct {
|
||||
@ -28,31 +27,23 @@ type Socks struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewSocks(link string) (*dialer.Dialer, error) {
|
||||
func NewSocks(log *logrus.Logger, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseSocksURL(link)
|
||||
if err != nil {
|
||||
return nil, dialer.InvalidParameterErr
|
||||
}
|
||||
return s.Dialer()
|
||||
return s.Dialer(log)
|
||||
}
|
||||
|
||||
func NewSocks5FromClashObj(o *yaml.Node) (*dialer.Dialer, error) {
|
||||
s, err := ParseClashSocks5(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer()
|
||||
}
|
||||
|
||||
func (s *Socks) Dialer() (*dialer.Dialer, error) {
|
||||
func (s *Socks) Dialer(log *logrus.Logger) (*dialer.Dialer, error) {
|
||||
link := s.ExportToURL()
|
||||
switch s.Protocol {
|
||||
case "", "socks", "socks5":
|
||||
d, err := socks5.NewSocks5Dialer(link, dialer.FullconeDirectDialer)
|
||||
d, err := socks5.NewSocks5Dialer(link, dialer.FullconeDirect) // Socks5 Proxy supports full-cone.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, true, s.Name, s.Protocol, link), nil
|
||||
return dialer.NewDialer(d, log, true, s.Name, s.Protocol, link), nil
|
||||
//case "socks4", "socks4a":
|
||||
// d, err := socks4.NewSocks4Dialer(link, &proxy.Direct{})
|
||||
// if err != nil {
|
||||
@ -64,37 +55,6 @@ func (s *Socks) Dialer() (*dialer.Dialer, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func ParseClashSocks5(o *yaml.Node) (data *Socks, err error) {
|
||||
type Socks5Option struct {
|
||||
Name string `yaml:"name"`
|
||||
Server string `yaml:"server"`
|
||||
Port int `yaml:"port"`
|
||||
UserName string `yaml:"username,omitempty"`
|
||||
Password string `yaml:"password,omitempty"`
|
||||
TLS bool `yaml:"tls,omitempty"`
|
||||
UDP bool `yaml:"udp,omitempty"`
|
||||
SkipCertVerify bool `yaml:"skip-cert-verify,omitempty"`
|
||||
}
|
||||
var option Socks5Option
|
||||
if err = o.Decode(&option); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if option.TLS {
|
||||
return nil, fmt.Errorf("%w: tls=true", dialer.UnexpectedFieldErr)
|
||||
}
|
||||
if option.SkipCertVerify {
|
||||
return nil, fmt.Errorf("%w: skip-cert-verify=true", dialer.UnexpectedFieldErr)
|
||||
}
|
||||
return &Socks{
|
||||
Name: option.Name,
|
||||
Server: option.Server,
|
||||
Port: option.Port,
|
||||
Username: option.UserName,
|
||||
Password: option.Password,
|
||||
Protocol: "socks5",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseSocksURL(link string) (data *Socks, err error) {
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
|
@ -2,13 +2,13 @@ package trojan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer/transport/tls"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer/transport/ws"
|
||||
"github.com/mzz2017/softwind/protocol"
|
||||
"github.com/mzz2017/softwind/transport/grpc"
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/component/outbound/transport/tls"
|
||||
"github.com/v2rayA/dae/component/outbound/transport/ws"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -18,7 +18,6 @@ import (
|
||||
func init() {
|
||||
dialer.FromLinkRegister("trojan", NewTrojan)
|
||||
dialer.FromLinkRegister("trojan-go", NewTrojan)
|
||||
dialer.FromClashRegister("trojan", NewTrojanFromClashObj)
|
||||
}
|
||||
|
||||
type Trojan struct {
|
||||
@ -36,24 +35,16 @@ type Trojan struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewTrojan(link string) (*dialer.Dialer, error) {
|
||||
func NewTrojan(log *logrus.Logger, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseTrojanURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer()
|
||||
return s.Dialer(log)
|
||||
}
|
||||
|
||||
func NewTrojanFromClashObj(o *yaml.Node) (*dialer.Dialer, error) {
|
||||
s, err := ParseClash(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer()
|
||||
}
|
||||
|
||||
func (s *Trojan) Dialer() (*dialer.Dialer, error) {
|
||||
d := dialer.SymmetricDirect
|
||||
func (s *Trojan) Dialer(log *logrus.Logger) (*dialer.Dialer, error) {
|
||||
d := dialer.FullconeDirect // Trojan Proxy supports full-cone.
|
||||
u := url.URL{
|
||||
Scheme: "tls",
|
||||
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
@ -111,7 +102,7 @@ func (s *Trojan) Dialer() (*dialer.Dialer, error) {
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, true, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
return dialer.NewDialer(d, log, true, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseTrojanURL(u string) (data *Trojan, err error) {
|
||||
@ -160,53 +151,6 @@ func ParseTrojanURL(u string) (data *Trojan, err error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func ParseClash(o *yaml.Node) (data *Trojan, err error) {
|
||||
type WSOptions struct {
|
||||
Path string `yaml:"path,omitempty"`
|
||||
Headers map[string]string `yaml:"headers,omitempty"`
|
||||
MaxEarlyData int `yaml:"max-early-data,omitempty"`
|
||||
EarlyDataHeaderName string `yaml:"early-data-header-name,omitempty"`
|
||||
}
|
||||
type GrpcOptions struct {
|
||||
GrpcServiceName string `proxy:"grpc-service-name,omitempty"`
|
||||
}
|
||||
type TrojanOption struct {
|
||||
Name string `yaml:"name"`
|
||||
Server string `yaml:"server"`
|
||||
Port int `yaml:"port"`
|
||||
Password string `yaml:"password"`
|
||||
ALPN []string `yaml:"alpn,omitempty"`
|
||||
SNI string `yaml:"sni,omitempty"`
|
||||
SkipCertVerify bool `yaml:"skip-cert-verify,omitempty"`
|
||||
UDP bool `yaml:"udp,omitempty"`
|
||||
Network string `yaml:"network,omitempty"`
|
||||
GrpcOpts GrpcOptions `yaml:"grpc-opts,omitempty"`
|
||||
WSOpts WSOptions `yaml:"ws-opts,omitempty"`
|
||||
}
|
||||
var option TrojanOption
|
||||
if err = o.Decode(&option); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proto := "trojan"
|
||||
if option.Network != "" && option.Network != "origin" {
|
||||
proto = "trojan-go"
|
||||
}
|
||||
return &Trojan{
|
||||
Name: option.Name,
|
||||
Server: option.Server,
|
||||
Port: option.Port,
|
||||
Password: option.Password,
|
||||
Sni: option.SNI,
|
||||
Type: option.Network,
|
||||
Encryption: "",
|
||||
Host: option.WSOpts.Headers["Host"],
|
||||
Path: option.WSOpts.Path,
|
||||
AllowInsecure: option.SkipCertVerify,
|
||||
ServiceName: option.GrpcOpts.GrpcServiceName,
|
||||
Protocol: proto,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *Trojan) ExportToURL() string {
|
||||
u := &url.URL{
|
||||
Scheme: "trojan",
|
||||
|
@ -3,25 +3,24 @@ package v2ray
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer/transport/tls"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer/transport/ws"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/mzz2017/softwind/protocol"
|
||||
"github.com/mzz2017/softwind/transport/grpc"
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/component/outbound/transport/tls"
|
||||
"github.com/v2rayA/dae/component/outbound/transport/ws"
|
||||
"golang.org/x/net/proxy"
|
||||
"net"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dialer.FromLinkRegister("vmess", NewV2Ray)
|
||||
dialer.FromLinkRegister("vless", NewV2Ray)
|
||||
dialer.FromClashRegister("vmess", NewVMessFromClashObj)
|
||||
}
|
||||
|
||||
type V2Ray struct {
|
||||
@ -43,7 +42,7 @@ type V2Ray struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewV2Ray(link string) (*dialer.Dialer, error) {
|
||||
func NewV2Ray(log *logrus.Logger, link string) (*dialer.Dialer, error) {
|
||||
var (
|
||||
s *V2Ray
|
||||
err error
|
||||
@ -65,21 +64,19 @@ func NewV2Ray(link string) (*dialer.Dialer, error) {
|
||||
default:
|
||||
return nil, dialer.InvalidParameterErr
|
||||
}
|
||||
return s.Dialer()
|
||||
return s.Dialer(log)
|
||||
}
|
||||
|
||||
func NewVMessFromClashObj(o *yaml.Node) (*dialer.Dialer, error) {
|
||||
s, err := ParseClashVMess(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (s *V2Ray) Dialer(log *logrus.Logger) (data *dialer.Dialer, err error) {
|
||||
var d proxy.Dialer
|
||||
switch s.Protocol {
|
||||
case "vmess":
|
||||
d = dialer.FullconeDirect // VMess Proxy supports full-cone.
|
||||
case "vless":
|
||||
d = dialer.SymmetricDirect // VLESS Proxy does not yet support full-cone by softwind.
|
||||
default:
|
||||
return nil, fmt.Errorf("V2Ray.Dialer: unexpected protocol: %v", s.Protocol)
|
||||
}
|
||||
return s.Dialer()
|
||||
}
|
||||
|
||||
func (s *V2Ray) Dialer() (data *dialer.Dialer, err error) {
|
||||
var (
|
||||
d = dialer.SymmetricDirect
|
||||
)
|
||||
|
||||
switch strings.ToLower(s.Net) {
|
||||
case "ws":
|
||||
@ -151,91 +148,9 @@ func (s *V2Ray) Dialer() (data *dialer.Dialer, err error) {
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, true, s.Ps, s.Protocol, s.ExportToURL()), nil
|
||||
return dialer.NewDialer(d, log, true, s.Ps, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseClashVMess(o *yaml.Node) (data *V2Ray, err error) {
|
||||
type WSOptions struct {
|
||||
Path string `yaml:"path,omitempty"`
|
||||
Headers map[string]string `yaml:"headers,omitempty"`
|
||||
MaxEarlyData int `yaml:"max-early-data,omitempty"`
|
||||
EarlyDataHeaderName string `yaml:"early-data-header-name,omitempty"`
|
||||
}
|
||||
type GrpcOptions struct {
|
||||
GrpcServiceName string `proxy:"grpc-service-name,omitempty"`
|
||||
}
|
||||
type HTTP2Options struct {
|
||||
Host []string `proxy:"host,omitempty"`
|
||||
Path string `proxy:"path,omitempty"`
|
||||
}
|
||||
type VmessOption struct {
|
||||
Name string `yaml:"name"`
|
||||
Server string `yaml:"server"`
|
||||
Port int `yaml:"port"`
|
||||
UUID string `yaml:"uuid"`
|
||||
AlterID int `yaml:"alterId"`
|
||||
Cipher string `yaml:"cipher"`
|
||||
UDP bool `yaml:"udp,omitempty"`
|
||||
Network string `yaml:"network,omitempty"`
|
||||
TLS bool `yaml:"tls,omitempty"`
|
||||
SkipCertVerify bool `yaml:"skip-cert-verify,omitempty"`
|
||||
ServerName string `yaml:"servername,omitempty"`
|
||||
HTTPOpts interface{} `yaml:"http-opts,omitempty"`
|
||||
HTTP2Opts HTTP2Options `yaml:"h2-opts,omitempty"`
|
||||
GrpcOpts GrpcOptions `yaml:"grpc-opts,omitempty"`
|
||||
WSOpts WSOptions `yaml:"ws-opts,omitempty"`
|
||||
}
|
||||
var option VmessOption
|
||||
if err = o.Decode(&option); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if option.Network == "" {
|
||||
option.Network = "tcp"
|
||||
}
|
||||
var (
|
||||
path string
|
||||
host string
|
||||
alpn string
|
||||
)
|
||||
switch option.Network {
|
||||
case "ws":
|
||||
path = option.WSOpts.Path
|
||||
host = option.WSOpts.Headers["Host"]
|
||||
alpn = "http/1.1"
|
||||
case "grpc":
|
||||
path = option.GrpcOpts.GrpcServiceName
|
||||
case "h2":
|
||||
host = strings.Join(option.HTTP2Opts.Host, ",")
|
||||
path = option.HTTP2Opts.Path
|
||||
alpn = "h2"
|
||||
case "http":
|
||||
// TODO
|
||||
}
|
||||
s := &V2Ray{
|
||||
Ps: option.Name,
|
||||
Add: option.Server,
|
||||
Port: strconv.Itoa(option.Port),
|
||||
ID: option.UUID,
|
||||
Aid: strconv.Itoa(option.AlterID),
|
||||
Net: option.Network,
|
||||
Type: "none", // FIXME
|
||||
Host: host,
|
||||
SNI: option.ServerName,
|
||||
Path: path,
|
||||
AllowInsecure: false,
|
||||
Alpn: alpn,
|
||||
V: "2",
|
||||
Protocol: "vmess",
|
||||
}
|
||||
if option.SkipCertVerify {
|
||||
return nil, fmt.Errorf("%w: skip-cert-verify=true", dialer.UnexpectedFieldErr)
|
||||
}
|
||||
if option.TLS {
|
||||
s.TLS = "tls"
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
func ParseVlessURL(vless string) (data *V2Ray, err error) {
|
||||
u, err := url.Parse(vless)
|
||||
if err != nil {
|
||||
|
@ -7,9 +7,9 @@ package outbound
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/proxy"
|
||||
"net"
|
||||
)
|
||||
@ -21,6 +21,7 @@ type DialerSelectionPolicy struct {
|
||||
|
||||
type DialerGroup struct {
|
||||
proxy.Dialer
|
||||
block *dialer.Dialer
|
||||
|
||||
log *logrus.Logger
|
||||
Name string
|
||||
@ -58,6 +59,7 @@ func NewDialerGroup(log *logrus.Logger, name string, dialers []*dialer.Dialer, p
|
||||
log: log,
|
||||
Name: name,
|
||||
Dialers: dialers,
|
||||
block: dialer.NewBlockDialer(log),
|
||||
AliveDialerSet: a,
|
||||
registeredAliveDialerSet: registeredAliveDialerSet,
|
||||
selectionPolicy: &p,
|
||||
@ -89,9 +91,8 @@ func (g *DialerGroup) Select() (*dialer.Dialer, error) {
|
||||
d := g.AliveDialerSet.GetRand()
|
||||
if d == nil {
|
||||
// No alive dialer.
|
||||
// TODO: Should we throw an error to block the connection in this condition?
|
||||
g.log.Warnf("No alive dialer in DialerGroup %v, use DIRECT. It may cause IP leaking.", g.Name)
|
||||
return dialer.FullconeDirectDialer, nil
|
||||
g.log.Warnf("No alive dialer in DialerGroup %v, use \"block\".", g.Name)
|
||||
return g.block, nil
|
||||
}
|
||||
return d, nil
|
||||
|
||||
@ -105,9 +106,8 @@ func (g *DialerGroup) Select() (*dialer.Dialer, error) {
|
||||
d := g.AliveDialerSet.GetMinLatency()
|
||||
if d == nil {
|
||||
// No alive dialer.
|
||||
// TODO: Should we throw an error to block the connection in this condition?
|
||||
g.log.Warnf("No alive dialer in DialerGroup %v, use DIRECT. It may cause IP leaking.", g.Name)
|
||||
return dialer.FullconeDirectDialer, nil
|
||||
g.log.Warnf("No alive dialer in DialerGroup %v, use \"block\".", g.Name)
|
||||
return g.block, nil
|
||||
}
|
||||
return d, nil
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
package outbound
|
||||
|
||||
import (
|
||||
"github.com/mzz2017/softwind/pkg/fastrand"
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/pkg/logger"
|
||||
"github.com/mzz2017/softwind/pkg/fastrand"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@ -17,8 +17,8 @@ import (
|
||||
func TestDialerGroup_Select_Fixed(t *testing.T) {
|
||||
log := logger.NewLogger(2)
|
||||
dialers := []*dialer.Dialer{
|
||||
dialer.SymmetricDirectDialer,
|
||||
dialer.FullconeDirectDialer,
|
||||
dialer.NewDirectDialer(log, true),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
}
|
||||
fixedIndex := 1
|
||||
g := NewDialerGroup(log, "test-group", dialers, DialerSelectionPolicy{
|
||||
@ -51,16 +51,16 @@ func TestDialerGroup_Select_Fixed(t *testing.T) {
|
||||
func TestDialerGroup_Select_MinLastLatency(t *testing.T) {
|
||||
log := logger.NewLogger(2)
|
||||
dialers := []*dialer.Dialer{
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
}
|
||||
g := NewDialerGroup(log, "test-group", dialers, DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_MinLastLatency,
|
||||
@ -114,11 +114,11 @@ func TestDialerGroup_Select_MinLastLatency(t *testing.T) {
|
||||
func TestDialerGroup_Select_Random(t *testing.T) {
|
||||
log := logger.NewLogger(2)
|
||||
dialers := []*dialer.Dialer{
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
}
|
||||
g := NewDialerGroup(log, "test-group", dialers, DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_Random,
|
||||
@ -147,11 +147,11 @@ func TestDialerGroup_Select_Random(t *testing.T) {
|
||||
func TestDialerGroup_SetAlive(t *testing.T) {
|
||||
log := logger.NewLogger(2)
|
||||
dialers := []*dialer.Dialer{
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDialer(dialer.SymmetricDirect, true, "direct", "direct", ""),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
dialer.NewDirectDialer(log, false),
|
||||
}
|
||||
g := NewDialerGroup(log, "test-group", dialers, DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_Random,
|
||||
|
@ -6,14 +6,14 @@
|
||||
package outbound
|
||||
|
||||
import (
|
||||
_ "github.com/mzz2017/softwind/protocol/shadowsocks"
|
||||
_ "github.com/mzz2017/softwind/protocol/trojanc"
|
||||
_ "github.com/mzz2017/softwind/protocol/vless"
|
||||
_ "github.com/mzz2017/softwind/protocol/vmess"
|
||||
_ "github.com/v2rayA/dae/component/outbound/dialer/http"
|
||||
_ "github.com/v2rayA/dae/component/outbound/dialer/shadowsocks"
|
||||
_ "github.com/v2rayA/dae/component/outbound/dialer/shadowsocksr"
|
||||
_ "github.com/v2rayA/dae/component/outbound/dialer/socks"
|
||||
_ "github.com/v2rayA/dae/component/outbound/dialer/trojan"
|
||||
_ "github.com/v2rayA/dae/component/outbound/dialer/v2ray"
|
||||
_ "github.com/mzz2017/softwind/protocol/shadowsocks"
|
||||
_ "github.com/mzz2017/softwind/protocol/trojanc"
|
||||
_ "github.com/mzz2017/softwind/protocol/vless"
|
||||
_ "github.com/mzz2017/softwind/protocol/vmess"
|
||||
)
|
||||
|
@ -19,14 +19,14 @@ type MatcherBuilder interface {
|
||||
AddDomain(key string, values []string, outbound string)
|
||||
AddIp(values []netip.Prefix, outbound string)
|
||||
AddPort(values [][2]int, outbound string)
|
||||
AddSource(values []netip.Prefix, outbound string)
|
||||
AddSourceIp(values []netip.Prefix, outbound string)
|
||||
AddSourcePort(values [][2]int, outbound string)
|
||||
AddL4Proto(values consts.L4ProtoType, outbound string)
|
||||
AddIpVersion(values consts.IpVersion, outbound string)
|
||||
AddMac(values [][6]byte, outbound string)
|
||||
AddSourceMac(values [][6]byte, outbound string)
|
||||
AddFinal(outbound string)
|
||||
AddAnyBefore(key string, values []string, outbound string)
|
||||
AddAnyAfter(key string, values []string, outbound string)
|
||||
AddAnyBefore(function string, key string, values []string, outbound string)
|
||||
AddAnyAfter(function string, key string, values []string, outbound string)
|
||||
Build() (err error)
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ func ApplyMatcherBuilder(builder MatcherBuilder, rules []RoutingRule, finalOutbo
|
||||
if iFunc == len(rule.AndFunctions)-1 {
|
||||
outbound = rule.Outbound
|
||||
}
|
||||
builder.AddAnyBefore(key, paramValueGroup, outbound)
|
||||
builder.AddAnyBefore(f.Name, key, paramValueGroup, outbound)
|
||||
switch f.Name {
|
||||
case consts.Function_Domain:
|
||||
builder.AddDomain(key, paramValueGroup, outbound)
|
||||
@ -77,7 +77,7 @@ func ApplyMatcherBuilder(builder MatcherBuilder, rules []RoutingRule, finalOutbo
|
||||
if f.Name == consts.Function_Ip {
|
||||
builder.AddIp(cidrs, outbound)
|
||||
} else {
|
||||
builder.AddSource(cidrs, outbound)
|
||||
builder.AddSourceIp(cidrs, outbound)
|
||||
}
|
||||
case consts.Function_Mac:
|
||||
var macAddrs [][6]byte
|
||||
@ -88,7 +88,7 @@ func ApplyMatcherBuilder(builder MatcherBuilder, rules []RoutingRule, finalOutbo
|
||||
}
|
||||
macAddrs = append(macAddrs, mac)
|
||||
}
|
||||
builder.AddMac(macAddrs, outbound)
|
||||
builder.AddSourceMac(macAddrs, outbound)
|
||||
case consts.Function_Port, consts.Function_SourcePort:
|
||||
var portRanges [][2]int
|
||||
for _, v := range paramValueGroup {
|
||||
@ -128,27 +128,29 @@ func ApplyMatcherBuilder(builder MatcherBuilder, rules []RoutingRule, finalOutbo
|
||||
default:
|
||||
return fmt.Errorf("unsupported function name: %v", f.Name)
|
||||
}
|
||||
builder.AddAnyAfter(key, paramValueGroup, outbound)
|
||||
builder.AddAnyAfter(f.Name, key, paramValueGroup, outbound)
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.AddAnyBefore("", nil, finalOutbound)
|
||||
builder.AddAnyBefore("final", "", nil, finalOutbound)
|
||||
builder.AddFinal(finalOutbound)
|
||||
builder.AddAnyAfter("", nil, finalOutbound)
|
||||
builder.AddAnyAfter("final", "", nil, finalOutbound)
|
||||
return nil
|
||||
}
|
||||
|
||||
type DefaultMatcherBuilder struct{}
|
||||
|
||||
func (d *DefaultMatcherBuilder) AddDomain(values []string, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddIp(values []netip.Prefix, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddPort(values [][2]int, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddSource(values []netip.Prefix, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddSourcePort(values [][2]int, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddL4Proto(values consts.L4ProtoType, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddIpVersion(values consts.IpVersion, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddMac(values [][6]byte, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddFinal(outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddAnyBefore(key string, values []string, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddAnyAfter(key string, values []string, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) Build() (err error) { return nil }
|
||||
func (d *DefaultMatcherBuilder) AddDomain(values []string, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddIp(values []netip.Prefix, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddPort(values [][2]int, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddSource(values []netip.Prefix, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddSourcePort(values [][2]int, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddL4Proto(values consts.L4ProtoType, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddIpVersion(values consts.IpVersion, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddMac(values [][6]byte, outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddFinal(outbound string) {}
|
||||
func (d *DefaultMatcherBuilder) AddAnyBefore(function string, key string, values []string, outbound string) {
|
||||
}
|
||||
func (d *DefaultMatcherBuilder) AddAnyAfter(function string, key string, values []string, outbound string) {
|
||||
}
|
||||
func (d *DefaultMatcherBuilder) Build() (err error) { return nil }
|
||||
|
@ -184,7 +184,7 @@ func (s *RoutingAWalker) EnterDeclaration(ctx *routingA.DeclarationContext) {
|
||||
switch valueCtx := children[2].(type) {
|
||||
case *routingA.LiteralContext:
|
||||
value := getValueFromLiteral(valueCtx)
|
||||
if key == "default" {
|
||||
if key == consts.Declaration_Final {
|
||||
s.FinalOutbound = value
|
||||
} else {
|
||||
s.ReportError(ctx, ErrorType_Unsupported)
|
||||
@ -201,6 +201,7 @@ func (s *RoutingAWalker) EnterDeclaration(ctx *routingA.DeclarationContext) {
|
||||
|
||||
func (s *RoutingAWalker) EnterRoutingRule(ctx *routingA.RoutingRuleContext) {
|
||||
children := ctx.GetChildren()
|
||||
//logrus.Debugln(ctx.GetText(), children)
|
||||
left, ok := children[0].(*routingA.RoutingRuleLeftContext)
|
||||
if !ok {
|
||||
s.ReportError(ctx, ErrorType_Unsupported, "not *RoutingRuleLeftContext: "+ctx.GetText())
|
||||
|
254
config/bind.go
Normal file
254
config/bind.go
Normal file
@ -0,0 +1,254 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/viper"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrRequired = fmt.Errorf("required")
|
||||
ErrMutualReference = fmt.Errorf("mutual reference or invalid value")
|
||||
ErrOverlayHierarchicalKey = fmt.Errorf("overlay hierarchical key")
|
||||
)
|
||||
|
||||
type Binder struct {
|
||||
viper *viper.Viper
|
||||
toResolve map[string]string
|
||||
resolved map[string]interface{}
|
||||
}
|
||||
|
||||
func MustGetMapKeys(m interface{}) (keys []string) {
|
||||
v := reflect.ValueOf(m)
|
||||
vKeys := v.MapKeys()
|
||||
for _, k := range vKeys {
|
||||
keys = append(keys, k.String())
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func NewBinder(viper *viper.Viper) *Binder {
|
||||
return &Binder{
|
||||
viper: viper,
|
||||
toResolve: make(map[string]string),
|
||||
resolved: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Binder) Bind(iface interface{}) error {
|
||||
if err := b.bind(iface); err != nil {
|
||||
return err
|
||||
}
|
||||
for len(b.toResolve) > 0 {
|
||||
var changed bool
|
||||
for key, expr := range b.toResolve {
|
||||
ok, err := b.bindKey(key, expr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
changed = true
|
||||
if err := SetValueHierarchicalMap(b.resolved, key, b.viper.Get(key)); err != nil {
|
||||
return fmt.Errorf("%w: %v", err, key)
|
||||
}
|
||||
delete(b.toResolve, key)
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
return fmt.Errorf("%v: %w", strings.Join(MustGetMapKeys(b.toResolve), ", "), ErrMutualReference)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Binder) bind(iface interface{}, parts ...string) error {
|
||||
// https://github.com/spf13/viper/issues/188
|
||||
ifv := reflect.ValueOf(iface)
|
||||
ift := reflect.TypeOf(iface)
|
||||
nextField:
|
||||
for i := 0; i < ift.NumField(); i++ {
|
||||
v := ifv.Field(i)
|
||||
t := ift.Field(i)
|
||||
tv, ok := t.Tag.Lookup("mapstructure")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
fields := strings.Split(tv, ",")
|
||||
tv = fields[0]
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
if err := b.bind(v.Interface(), append(parts, tv)...); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
key := strings.Join(append(parts, tv), ".")
|
||||
if b.viper.Get(key) == nil {
|
||||
if defaultValue, ok := t.Tag.Lookup("default"); ok {
|
||||
ok, err := b.bindKey(key, defaultValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
b.toResolve[key] = defaultValue
|
||||
continue nextField
|
||||
}
|
||||
} else if _, ok := t.Tag.Lookup("required"); ok {
|
||||
if desc, ok := t.Tag.Lookup("desc"); ok {
|
||||
key += " (" + desc + ")"
|
||||
}
|
||||
return fmt.Errorf("%w: %v", ErrRequired, key)
|
||||
} else if len(fields) == 1 || fields[1] != "omitempty" {
|
||||
// write an empty value
|
||||
b.viper.Set(key, "")
|
||||
}
|
||||
}
|
||||
if err := SetValueHierarchicalMap(b.resolved, key, b.viper.Get(key)); err != nil {
|
||||
return fmt.Errorf("%w: %v", err, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Binder) bindKey(key string, expr string) (ok bool, err error) {
|
||||
b.viper.Set(key, expr)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func SetValueHierarchicalMap(m map[string]interface{}, key string, val interface{}) error {
|
||||
keys := strings.Split(key, ".")
|
||||
lastKey := keys[len(keys)-1]
|
||||
keys = keys[:len(keys)-1]
|
||||
p := &m
|
||||
for _, key := range keys {
|
||||
if v, ok := (*p)[key]; ok {
|
||||
vv, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
return ErrOverlayHierarchicalKey
|
||||
}
|
||||
p = &vv
|
||||
} else {
|
||||
(*p)[key] = make(map[string]interface{})
|
||||
vv := (*p)[key].(map[string]interface{})
|
||||
p = &vv
|
||||
}
|
||||
}
|
||||
(*p)[lastKey] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetValueHierarchicalStruct(m interface{}, key string, val string) error {
|
||||
ifv, err := GetValueHierarchicalStruct(m, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !FuzzyDecode(ifv.Addr().Interface(), val) {
|
||||
return fmt.Errorf("type does not match: type \"%v\" and value \"%v\"", ifv.Kind(), val)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetValueHierarchicalStruct(m interface{}, key string) (reflect.Value, error) {
|
||||
keys := strings.Split(key, ".")
|
||||
ifv := reflect.Indirect(reflect.ValueOf(m))
|
||||
ift := ifv.Type()
|
||||
lastK := ""
|
||||
for _, k := range keys {
|
||||
found := false
|
||||
if ift.Kind() == reflect.Struct {
|
||||
for i := 0; i < ifv.NumField(); i++ {
|
||||
name, ok := ift.Field(i).Tag.Lookup("mapstructure")
|
||||
if ok && name == k {
|
||||
found = true
|
||||
ifv = ifv.Field(i)
|
||||
ift = ifv.Type()
|
||||
lastK = k
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return reflect.Value{}, fmt.Errorf(`unexpected key "%v": "%v" (%v type) has no member "%v"`, key, lastK, ift.Kind().String(), k)
|
||||
}
|
||||
}
|
||||
return ifv, nil
|
||||
}
|
||||
|
||||
func FuzzyDecode(to interface{}, val string) bool {
|
||||
v := reflect.Indirect(reflect.ValueOf(to))
|
||||
switch v.Kind() {
|
||||
case reflect.Int:
|
||||
i, err := strconv.ParseInt(val, 10, strconv.IntSize)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetInt(i)
|
||||
case reflect.Int8:
|
||||
i, err := strconv.ParseInt(val, 10, 8)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetInt(i)
|
||||
case reflect.Int16:
|
||||
i, err := strconv.ParseInt(val, 10, 16)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetInt(i)
|
||||
case reflect.Int32:
|
||||
i, err := strconv.ParseInt(val, 10, 32)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetInt(i)
|
||||
case reflect.Int64:
|
||||
i, err := strconv.ParseInt(val, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetInt(i)
|
||||
case reflect.Uint:
|
||||
i, err := strconv.ParseUint(val, 10, strconv.IntSize)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetUint(i)
|
||||
case reflect.Uint8:
|
||||
i, err := strconv.ParseUint(val, 10, 8)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetUint(i)
|
||||
case reflect.Uint16:
|
||||
i, err := strconv.ParseUint(val, 10, 16)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetUint(i)
|
||||
case reflect.Uint32:
|
||||
i, err := strconv.ParseUint(val, 10, 32)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetUint(i)
|
||||
case reflect.Uint64:
|
||||
i, err := strconv.ParseUint(val, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
v.SetUint(i)
|
||||
case reflect.Bool:
|
||||
if val == "true" || val == "1" {
|
||||
v.SetBool(true)
|
||||
} else if val == "false" || val == "0" {
|
||||
v.SetBool(false)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case reflect.String:
|
||||
v.SetString(val)
|
||||
}
|
||||
return true
|
||||
}
|
26
config/config.go
Normal file
26
config/config.go
Normal file
@ -0,0 +1,26 @@
|
||||
package config
|
||||
|
||||
type Subscription struct {
|
||||
Link string `mapstructure:"link"`
|
||||
Select string `mapstructure:"select" default:"first"`
|
||||
CacheLastNode bool `mapstructure:"cache_last_node" default:"true"`
|
||||
}
|
||||
type Cache struct {
|
||||
Subscription CacheSubscription `mapstructure:"subscription"`
|
||||
}
|
||||
type CacheSubscription struct {
|
||||
LastNode string `mapstructure:"last_node"`
|
||||
}
|
||||
type Params struct {
|
||||
Node string `mapstructure:"node"`
|
||||
Subscription Subscription `mapstructure:"subscription"`
|
||||
|
||||
Cache Cache `mapstructure:"cache"`
|
||||
|
||||
NoUDP bool `mapstructure:"no_udp"`
|
||||
|
||||
TestNode bool `mapstructure:"test_node_before_use" default:"true"`
|
||||
TestURL string `mapstructure:"test_url" default:"https://connectivitycheck.gstatic.com/generate_204"`
|
||||
}
|
||||
|
||||
var ParamsObj Params
|
34
go.mod
34
go.mod
@ -5,20 +5,21 @@ go 1.19
|
||||
require (
|
||||
github.com/adrg/xdg v0.4.0
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12
|
||||
github.com/cilium/ebpf v0.9.3
|
||||
github.com/cilium/ebpf v0.10.0
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||
github.com/mzz2017/softwind v0.0.0-20230124072602-aabc556ba332
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/v2fly/v2ray-core/v5 v5.2.1
|
||||
github.com/v2rayA/RoutingA-dist/go/routingA v0.0.0-20230124054934-e2204d89186f
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/viper v1.15.0
|
||||
github.com/v2rayA/RoutingA-dist/go/routingA v0.0.0-20230124191403-ef9c0530cb53
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230126180746-eae2d0e30c27
|
||||
github.com/v2rayA/shadowsocksR v1.0.4
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
golang.org/x/net v0.5.0
|
||||
golang.org/x/sys v0.4.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
@ -27,19 +28,36 @@ require (
|
||||
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect
|
||||
github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152 // indirect
|
||||
github.com/eknkc/basex v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mzz2017/disk-bloom v1.0.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect
|
||||
github.com/spf13/afero v1.9.3 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||
gitlab.com/yawning/chacha20.git v0.0.0-20190903091407-6d1cb28dc72c // indirect
|
||||
golang.org/x/crypto v0.5.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/text v0.6.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 // indirect
|
||||
google.golang.org/grpc v1.51.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
|
||||
google.golang.org/grpc v1.52.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
//replace github.com/mzz2017/softwind => /home/mzz/goProjects/softwind
|
||||
replace github.com/mzz2017/softwind => /home/mzz/goProjects/softwind
|
||||
|
||||
//replace github.com/cilium/ebpf => /home/mzz/goProjects/ebpf
|
||||
//replace github.com/v2rayA/RoutingA-dist/go/routingA => /home/mzz/antlrProjects/RoutingA-antlr4/build/go/routingA
|
||||
//replace github.com/v2rayA/dae-config-dist/go/dae_config => /home/mzz/antlrProjects/dae-config/build/go/dae_config
|
||||
|
417
go.sum
417
go.sum
@ -1,20 +1,58 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
|
||||
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 h1:npHgfD4Tl2WJS3AJaMUi5ynGDPUBfkg3U3fCzDyXZ+4=
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cilium/ebpf v0.9.3 h1:5KtxXZU+scyERvkJMEm16TbScVvuuMrlhPly78ZMbSc=
|
||||
github.com/cilium/ebpf v0.9.3/go.mod h1:w27N4UjpaQ9X/DGrSugxUG+H+NhgntDuPb5lCzxCn8A=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.10.0 h1:nk5HPMeoBXtOzbkZBWym+ZWq1GIiHUsBFXxwewXAHLQ=
|
||||
github.com/cilium/ebpf v0.10.0/go.mod h1:DPiVdY/kT534dgc9ERmvP8mWA+9gvwgKfRvk4nNWnoE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
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=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -33,16 +71,32 @@ github.com/eknkc/basex v1.0.1/go.mod h1:k/F/exNEHFdbs3ZHuasoP2E7zeWwZblG84Y7Z59v
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
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.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
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.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
@ -54,61 +108,122 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/mzz2017/disk-bloom v1.0.1 h1:rEF9MiXd9qMW3ibRpqcerLXULoTgRlM21yqqJl1B90M=
|
||||
github.com/mzz2017/disk-bloom v1.0.1/go.mod h1:JLHETtUu44Z6iBmsqzkOtFlRvXSlKnxjwiBRDapizDI=
|
||||
github.com/mzz2017/softwind v0.0.0-20230124072602-aabc556ba332 h1:wIHkkJcBo3ln0cdl607LAg+O8yj7oLQ3FIlBhLfWxUo=
|
||||
github.com/mzz2017/softwind v0.0.0-20230124072602-aabc556ba332/go.mod h1:K1nXwtBokwEsfOfdT/5zV6R8QabGkyhcR0iuTrRZcYY=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
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/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
|
||||
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
|
||||
github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/v2fly/v2ray-core/v5 v5.2.1 h1:bWc0cxvzCbbcsIE7/C+NFeUytQJYWgjtcRMG242I2Rs=
|
||||
github.com/v2fly/v2ray-core/v5 v5.2.1/go.mod h1:7MBSerlH+Wyq9Bvm90txc8Ey9C9MAwkM+ZtkMbKT0Zo=
|
||||
github.com/v2rayA/RoutingA-dist/go/routingA v0.0.0-20230124054934-e2204d89186f h1:qmnamMCAaJbGw+XtQJfTGtL3gm7+7dYMY8neh+MTUkE=
|
||||
github.com/v2rayA/RoutingA-dist/go/routingA v0.0.0-20230124054934-e2204d89186f/go.mod h1:BGhPbUF5jE2YhQiomx2F48N2lVNppcAlNCGfVhf5Lx4=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/v2rayA/RoutingA-dist/go/routingA v0.0.0-20230124191403-ef9c0530cb53 h1:seZfccOo70jrXD4LZAvM7AbW6IFXY2r230GgV7tsnro=
|
||||
github.com/v2rayA/RoutingA-dist/go/routingA v0.0.0-20230124191403-ef9c0530cb53/go.mod h1:BGhPbUF5jE2YhQiomx2F48N2lVNppcAlNCGfVhf5Lx4=
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230126180746-eae2d0e30c27 h1:IXDCb9A8PBdB+bBMVdCBP3c61DzUqLYQ4lb6tw8RXOo=
|
||||
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230126180746-eae2d0e30c27/go.mod h1:JiTWeZybOkBfCqv/fy5jbFhXTxuLlyrI76gRNazz2sU=
|
||||
github.com/v2rayA/shadowsocksR v1.0.4 h1:65Ltdy+I/DnlkQTJj+R+X85zhZ63ORE1Roy+agAcF/s=
|
||||
github.com/v2rayA/shadowsocksR v1.0.4/go.mod h1:CyOhDLy8/AKedsi16xRYAMmkxSCH1ukJPaacaTdRfQg=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
@ -116,97 +231,306 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
gitlab.com/yawning/chacha20.git v0.0.0-20190903091407-6d1cb28dc72c h1:yrfrd1u7MWIwWIulet2TZPEkeNQhQ/GcPLdPXgiEEr0=
|
||||
gitlab.com/yawning/chacha20.git v0.0.0-20190903091407-6d1cb28dc72c/go.mod h1:3x6b94nWCP/a2XB/joOPMiGYUBvqbLfeY/BkHLeDs6s=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
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/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/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-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
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=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 h1:z+ErRPu0+KS02Td3fOAgdX+lnPDh/VyaABEJPD4JRQs=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
|
||||
google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@ -215,20 +539,31 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
@ -5,11 +5,13 @@ sudo tc qdisc add dev $dev clsact > /dev/null 2>&1
|
||||
|
||||
set -ex
|
||||
|
||||
# clang -fno-stack-protector -O2 -g -emit-llvm -c component/control/kern/tproxy.c -o - | llc -march=bpf -mcpu=probe -filetype=obj -o foo.o
|
||||
sudo rm -rf /sys/fs/bpf/tc/globals/*
|
||||
|
||||
# clang -fno-stack-protector -O2 -g -emit-llvm -c component/control/kern/tproxy.c -o - | llc -march=bpf -mcpu=v3 -filetype=obj -o foo.o
|
||||
clang -O2 -g -Wall -Werror -c component/control/kern/tproxy.c -target bpf -o foo.o
|
||||
sudo tc filter del dev $dev ingress
|
||||
sudo tc filter add dev $dev ingress bpf direct-action obj foo.o sec tc/ingress
|
||||
sudo tc filter del dev $dev egress
|
||||
sudo tc filter add dev $dev ingress bpf direct-action obj foo.o sec tc/ingress
|
||||
sudo tc filter add dev $dev egress bpf direct-action obj foo.o sec tc/egress
|
||||
|
||||
exit 0
|
52
main.go
52
main.go
@ -8,51 +8,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/component/control"
|
||||
"github.com/v2rayA/dae/pkg/logger"
|
||||
"github.com/json-iterator/go/extra"
|
||||
"github.com/v2rayA/dae/cmd"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
const (
|
||||
tproxyPort = 12345
|
||||
ifname = "docker0"
|
||||
)
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
log := logger.NewLogger(2)
|
||||
log.Println("Running")
|
||||
t, err := control.NewControlPlane(log, `
|
||||
default:proxy
|
||||
#sip(172.17.0.2)->proxy
|
||||
#mac("02:42:ac:11:00:02")->proxy
|
||||
#ipversion(4)->proxy
|
||||
#l4proto(tcp)->proxy
|
||||
ip(119.29.29.29) -> proxy
|
||||
ip(223.5.5.5) -> direct
|
||||
ip(geoip:cn) -> direct
|
||||
domain(geosite:cn, suffix:"ip.sb") -> direct
|
||||
ip("91.105.192.0/23","91.108.4.0/22","91.108.8.0/21","91.108.16.0/21","91.108.56.0/22","95.161.64.0/20","149.154.160.0/20","185.76.151.0/24")->proxy
|
||||
domain(geosite:category-scholar-!cn, geosite:category-scholar-cn)->direct
|
||||
`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = t.BindLink(ifname); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGILL)
|
||||
go func() {
|
||||
if err := t.ListenAndServe(tproxyPort); err != nil {
|
||||
log.Errorln("ListenAndServe:", err)
|
||||
sigs <- nil
|
||||
}
|
||||
}()
|
||||
<-sigs
|
||||
if e := t.Close(); e != nil {
|
||||
log.Errorln("Close control plane:", err)
|
||||
extra.RegisterFuzzyDecoders()
|
||||
|
||||
http.DefaultClient.Timeout = 30 * time.Second
|
||||
if err := cmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
34
pkg/config_parser/config_parser.go
Normal file
34
pkg/config_parser/config_parser.go
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2023, mzz2017 (mzz@tuta.io). All rights reserved.
|
||||
*/
|
||||
|
||||
package config_parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr/v4"
|
||||
"github.com/v2rayA/dae-config-dist/go/dae_config"
|
||||
)
|
||||
|
||||
func Parse(in string) (sections []*Section, err error) {
|
||||
errorListener := NewConsoleErrorListener()
|
||||
lexer := dae_config.Newdae_configLexer(antlr.NewInputStream(in))
|
||||
lexer.RemoveErrorListeners()
|
||||
lexer.AddErrorListener(errorListener)
|
||||
input := antlr.NewCommonTokenStream(lexer, 0)
|
||||
|
||||
parser := dae_config.Newdae_configParser(input)
|
||||
parser.RemoveErrorListeners()
|
||||
parser.AddErrorListener(errorListener)
|
||||
parser.BuildParseTrees = true
|
||||
tree := parser.Start()
|
||||
|
||||
walker := NewWalker(parser)
|
||||
antlr.ParseTreeWalkerDefault.Walk(walker, tree)
|
||||
if errorListener.ErrorBuilder.Len() != 0 {
|
||||
return nil, fmt.Errorf("%v", errorListener.ErrorBuilder.String())
|
||||
}
|
||||
|
||||
return walker.Sections, nil
|
||||
}
|
91
pkg/config_parser/config_parser_test.go
Normal file
91
pkg/config_parser/config_parser_test.go
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2023, mzz2017 (mzz@tuta.io). All rights reserved.
|
||||
*/
|
||||
|
||||
package config_parser
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
sections, err := Parse(`
|
||||
# gugu
|
||||
include {
|
||||
another.conf
|
||||
}
|
||||
|
||||
global {
|
||||
# tproxy port to listen.
|
||||
tproxy_port: 12345
|
||||
|
||||
# Node connectivity check url.
|
||||
check_url: 'https://connectivitycheck.gstatic.com/generate_204'
|
||||
|
||||
# Now only support UDP and IP:Port.
|
||||
# Please make sure DNS traffic will go through and be forwarded by dae.
|
||||
dns_upstream: '1.1.1.1:53'
|
||||
|
||||
# Now only support one interface.
|
||||
ingress_interface: docker0
|
||||
}
|
||||
|
||||
# subscription will be resolved as nodes and merged into node pool below.
|
||||
subscription {
|
||||
https://LINK
|
||||
}
|
||||
|
||||
node {
|
||||
'ss://LINK'
|
||||
'ssr://LINK'
|
||||
'vmess://LINK'
|
||||
'vless://LINK'
|
||||
'trojan://LINK'
|
||||
'trojan-go://LINK'
|
||||
'socks5://LINK#name'
|
||||
'http://LINK#name'
|
||||
'https://LINK#name'
|
||||
}
|
||||
|
||||
group {
|
||||
my_group {
|
||||
# Pass node links as input of lua script filter.
|
||||
# gugu
|
||||
filter: link(lua:filename.lua)
|
||||
|
||||
# Randomly select a node from the group for every connection.
|
||||
policy: random
|
||||
}
|
||||
|
||||
disney {
|
||||
# Pass node names as input of keyword/regex filter.
|
||||
filter: name(regex:'^.*hk.*$', keyword:'sg') && name(keyword:'disney')
|
||||
|
||||
# Select the node with min average of the last 10 latencies from the group for every connection.
|
||||
policy: min_avg10
|
||||
}
|
||||
|
||||
netflix {
|
||||
# Pass node names as input of keyword filter.
|
||||
filter: name(keyword:netflix)
|
||||
|
||||
# Select the first node from the group for every connection.
|
||||
policy: fixed(0)
|
||||
}
|
||||
}
|
||||
|
||||
routing {
|
||||
domain(geosite:category-ads) -> block
|
||||
domain(geosite:disney) -> disney
|
||||
domain(geosite:netflix) -> netflix
|
||||
ip(geoip:cn) -> direct
|
||||
domain(geosite:cn) -> direct
|
||||
final: my_group
|
||||
}
|
||||
`)
|
||||
if err != nil {
|
||||
t.Fatalf("\n%v", err)
|
||||
}
|
||||
for _, section := range sections {
|
||||
t.Logf("\n%v", section.String())
|
||||
}
|
||||
}
|
91
pkg/config_parser/error.go
Normal file
91
pkg/config_parser/error.go
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2022, mzz2017 (mzz@tuta.io). All rights reserved.
|
||||
*/
|
||||
|
||||
package config_parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr/v4"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ErrorType string
|
||||
|
||||
const (
|
||||
ErrorType_Unsupported ErrorType = "is not supported"
|
||||
ErrorType_NotSet ErrorType = "is not set"
|
||||
)
|
||||
|
||||
type ConsoleErrorListener struct {
|
||||
ErrorBuilder strings.Builder
|
||||
}
|
||||
|
||||
func NewConsoleErrorListener() *ConsoleErrorListener {
|
||||
return &ConsoleErrorListener{}
|
||||
}
|
||||
|
||||
func (d *ConsoleErrorListener) SyntaxError(recognizer antlr.Recognizer, offendingSymbol interface{}, line, column int, msg string, e antlr.RecognitionException) {
|
||||
// Do not accumulate errors.
|
||||
if d.ErrorBuilder.Len() > 0 {
|
||||
return
|
||||
}
|
||||
backtrack := column
|
||||
if backtrack > 30 {
|
||||
backtrack = 30
|
||||
}
|
||||
starting := fmt.Sprintf("line %v:%v ", line, column)
|
||||
offset := len(starting) + backtrack
|
||||
var (
|
||||
simplyWrite bool
|
||||
token antlr.Token
|
||||
)
|
||||
if offendingSymbol == nil {
|
||||
simplyWrite = true
|
||||
} else {
|
||||
token = offendingSymbol.(antlr.Token)
|
||||
simplyWrite = token.GetTokenType() == -1
|
||||
}
|
||||
if simplyWrite {
|
||||
d.ErrorBuilder.WriteString(fmt.Sprintf("%v%v", starting, msg))
|
||||
return
|
||||
}
|
||||
|
||||
beginOfLine := token.GetStart() - backtrack
|
||||
strPeek := token.GetInputStream().GetText(beginOfLine, token.GetStop()+30)
|
||||
wrap := strings.IndexByte(strPeek, '\n')
|
||||
if wrap == -1 {
|
||||
wrap = token.GetStop() + 30
|
||||
} else {
|
||||
wrap += beginOfLine - 1
|
||||
}
|
||||
strLine := token.GetInputStream().GetText(beginOfLine, wrap)
|
||||
d.ErrorBuilder.WriteString(fmt.Sprintf("%v%v\n%v%v: %v\n", starting, strLine, strings.Repeat(" ", offset), strings.Repeat("^", token.GetStop()-token.GetStart()+1), msg))
|
||||
}
|
||||
func (d *ConsoleErrorListener) ReportAmbiguity(recognizer antlr.Parser, dfa *antlr.DFA, startIndex, stopIndex int, exact bool, ambigAlts *antlr.BitSet, configs antlr.ATNConfigSet) {
|
||||
}
|
||||
|
||||
func (d *ConsoleErrorListener) ReportAttemptingFullContext(recognizer antlr.Parser, dfa *antlr.DFA, startIndex, stopIndex int, conflictingAlts *antlr.BitSet, configs antlr.ATNConfigSet) {
|
||||
}
|
||||
|
||||
func (d *ConsoleErrorListener) ReportContextSensitivity(recognizer antlr.Parser, dfa *antlr.DFA, startIndex, stopIndex, prediction int, configs antlr.ATNConfigSet) {
|
||||
}
|
||||
|
||||
func BaseContext(ctx interface{}) (baseCtx *antlr.BaseParserRuleContext) {
|
||||
val := reflect.ValueOf(ctx)
|
||||
for val.Kind() == reflect.Pointer && val.Type() != reflect.TypeOf(&antlr.BaseParserRuleContext{}) {
|
||||
val = val.Elem()
|
||||
}
|
||||
if val.Type() == reflect.TypeOf(&antlr.BaseParserRuleContext{}) {
|
||||
baseCtx = val.Interface().(*antlr.BaseParserRuleContext)
|
||||
} else {
|
||||
baseCtxVal := val.FieldByName("BaseParserRuleContext")
|
||||
if !baseCtxVal.IsValid() {
|
||||
panic("has no field BaseParserRuleContext")
|
||||
}
|
||||
baseCtx = baseCtxVal.Interface().(*antlr.BaseParserRuleContext)
|
||||
}
|
||||
return baseCtx
|
||||
}
|
187
pkg/config_parser/section.go
Normal file
187
pkg/config_parser/section.go
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2023, mzz2017 (mzz@tuta.io). All rights reserved.
|
||||
*/
|
||||
|
||||
package config_parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ItemType int
|
||||
|
||||
const (
|
||||
ItemType_RoutingRule ItemType = iota
|
||||
ItemType_Param
|
||||
ItemType_Section
|
||||
)
|
||||
|
||||
func (t ItemType) String() string {
|
||||
switch t {
|
||||
case ItemType_RoutingRule:
|
||||
return "RoutingRule"
|
||||
case ItemType_Param:
|
||||
return "Param"
|
||||
case ItemType_Section:
|
||||
return "Section"
|
||||
default:
|
||||
return "<Unknown>"
|
||||
}
|
||||
}
|
||||
|
||||
func NewRoutingRuleItem(rule *RoutingRule) *Item {
|
||||
return &Item{
|
||||
Type: ItemType_RoutingRule,
|
||||
Value: rule,
|
||||
}
|
||||
}
|
||||
|
||||
func NewParamItem(param *Param) *Item {
|
||||
return &Item{
|
||||
Type: ItemType_Param,
|
||||
Value: param,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSectionItem(section *Section) *Item {
|
||||
return &Item{
|
||||
Type: ItemType_Param,
|
||||
Value: section,
|
||||
}
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
Type ItemType
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
func (i *Item) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("type: " + i.Type.String() + "\n")
|
||||
var content string
|
||||
switch val := i.Value.(type) {
|
||||
case *RoutingRule:
|
||||
content = val.String(false)
|
||||
case *Param:
|
||||
content = val.String()
|
||||
case *Section:
|
||||
content = val.String()
|
||||
default:
|
||||
return "<Unknown>\n"
|
||||
}
|
||||
lines := strings.Split(content, "\n")
|
||||
for i := range lines {
|
||||
lines[i] = "\t" + lines[i]
|
||||
}
|
||||
builder.WriteString(strings.Join(lines, "\n"))
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
type Section struct {
|
||||
Name string
|
||||
Items []*Item
|
||||
}
|
||||
|
||||
func (s *Section) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("section: " + s.Name + "\n")
|
||||
var strItemList []string
|
||||
for _, item := range s.Items {
|
||||
lines := strings.Split(item.String(), "\n")
|
||||
for i := range lines {
|
||||
lines[i] = "\t" + lines[i]
|
||||
}
|
||||
strItemList = append(strItemList, strings.Join(lines, "\n"))
|
||||
}
|
||||
builder.WriteString(strings.Join(strItemList, "\n"))
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
type Param struct {
|
||||
Key string
|
||||
Val string
|
||||
AndFunctions []*Function
|
||||
}
|
||||
|
||||
func (p *Param) String() string {
|
||||
if p.Key == "" {
|
||||
return p.Val
|
||||
}
|
||||
if p.AndFunctions != nil {
|
||||
a := paramAndFunctions{
|
||||
Key: p.Key,
|
||||
AndFunctions: p.AndFunctions,
|
||||
}
|
||||
return a.String()
|
||||
}
|
||||
return p.Key + ": " + p.Val
|
||||
}
|
||||
|
||||
type Function struct {
|
||||
Name string
|
||||
Params []*Param
|
||||
}
|
||||
|
||||
func (f *Function) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString(f.Name + "(")
|
||||
var strParamList []string
|
||||
for _, p := range f.Params {
|
||||
strParamList = append(strParamList, p.String())
|
||||
}
|
||||
builder.WriteString(strings.Join(strParamList, ", "))
|
||||
builder.WriteString(")")
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
type paramAndFunctions struct {
|
||||
Key string
|
||||
AndFunctions []*Function
|
||||
}
|
||||
|
||||
func (p *paramAndFunctions) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString(p.Key + ": ")
|
||||
var strFunctionList []string
|
||||
for _, f := range p.AndFunctions {
|
||||
strFunctionList = append(strFunctionList, f.String())
|
||||
}
|
||||
builder.WriteString(strings.Join(strFunctionList, " && "))
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
type RoutingRule struct {
|
||||
AndFunctions []*Function
|
||||
Outbound string
|
||||
}
|
||||
|
||||
func (r *RoutingRule) String(calcN bool) string {
|
||||
var builder strings.Builder
|
||||
var n int
|
||||
for _, f := range r.AndFunctions {
|
||||
if builder.Len() != 0 {
|
||||
builder.WriteString(" && ")
|
||||
}
|
||||
var paramBuilder strings.Builder
|
||||
n += len(f.Params)
|
||||
for _, p := range f.Params {
|
||||
if paramBuilder.Len() != 0 {
|
||||
paramBuilder.WriteString(", ")
|
||||
}
|
||||
if p.Key != "" {
|
||||
paramBuilder.WriteString(p.Key + ": " + p.Val)
|
||||
} else {
|
||||
paramBuilder.WriteString(p.Val)
|
||||
}
|
||||
}
|
||||
builder.WriteString(fmt.Sprintf("%v(%v)", f.Name, paramBuilder.String()))
|
||||
}
|
||||
builder.WriteString(" -> " + r.Outbound)
|
||||
if calcN {
|
||||
builder.WriteString(" [n = " + strconv.Itoa(n) + "]")
|
||||
}
|
||||
return builder.String()
|
||||
}
|
239
pkg/config_parser/walker.go
Normal file
239
pkg/config_parser/walker.go
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Copyright (c) since 2022, mzz2017 (mzz@tuta.io). All rights reserved.
|
||||
*/
|
||||
|
||||
package config_parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr/v4"
|
||||
"github.com/v2rayA/dae-config-dist/go/dae_config"
|
||||
"log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Walker struct {
|
||||
*dae_config.Basedae_configListener
|
||||
parser antlr.Parser
|
||||
|
||||
Sections []*Section
|
||||
}
|
||||
|
||||
func NewWalker(parser antlr.Parser) *Walker {
|
||||
return &Walker{
|
||||
parser: parser,
|
||||
}
|
||||
}
|
||||
|
||||
type paramParser struct {
|
||||
list []*Param
|
||||
}
|
||||
|
||||
func getValueFromLiteral(literal *dae_config.LiteralContext) string {
|
||||
quote := literal.Quote_literal()
|
||||
if quote == nil {
|
||||
return literal.GetText()
|
||||
}
|
||||
text := quote.GetText()
|
||||
return text[1 : len(text)-1]
|
||||
}
|
||||
|
||||
func (p *paramParser) parseParam(ctx *dae_config.ParameterContext) *Param {
|
||||
children := ctx.GetChildren()
|
||||
if len(children) == 3 {
|
||||
return &Param{
|
||||
Key: children[0].(*antlr.TerminalNodeImpl).GetText(),
|
||||
Val: getValueFromLiteral(children[2].(*dae_config.LiteralContext)),
|
||||
}
|
||||
} else if len(children) == 1 {
|
||||
return &Param{
|
||||
Key: "",
|
||||
Val: getValueFromLiteral(children[0].(*dae_config.LiteralContext)),
|
||||
}
|
||||
}
|
||||
panic("unexpected")
|
||||
}
|
||||
func (p *paramParser) parseNonEmptyParamList(ctx *dae_config.NonEmptyParameterListContext) {
|
||||
children := ctx.GetChildren()
|
||||
if len(children) == 3 {
|
||||
p.list = append(p.list, p.parseParam(children[2].(*dae_config.ParameterContext)))
|
||||
p.parseNonEmptyParamList(children[0].(*dae_config.NonEmptyParameterListContext))
|
||||
} else if len(children) == 1 {
|
||||
p.list = append(p.list, p.parseParam(children[0].(*dae_config.ParameterContext)))
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Walker) parseNonEmptyParamList(list *dae_config.NonEmptyParameterListContext) []*Param {
|
||||
paramParser := new(paramParser)
|
||||
paramParser.parseNonEmptyParamList(list)
|
||||
return paramParser.list
|
||||
}
|
||||
|
||||
func (w *Walker) reportKeyUnsupportedError(ctx interface{}, keyName, funcName string) {
|
||||
w.ReportError(ctx, ErrorType_Unsupported, fmt.Sprintf("key %v in %v()", strconv.Quote(keyName), funcName))
|
||||
}
|
||||
|
||||
type functionVerifier func(function *Function, ctx interface{}) bool
|
||||
|
||||
func (w *Walker) parseFunctionPrototype(ctx *dae_config.FunctionPrototypeContext, verifier functionVerifier) *Function {
|
||||
children := ctx.GetChildren()
|
||||
funcName := children[0].(*antlr.TerminalNodeImpl).GetText()
|
||||
paramList := children[2].(*dae_config.OptParameterListContext)
|
||||
children = paramList.GetChildren()
|
||||
if len(children) == 0 {
|
||||
w.ReportError(ctx, ErrorType_Unsupported, "empty parameter list")
|
||||
return nil
|
||||
}
|
||||
nonEmptyParamList := children[0].(*dae_config.NonEmptyParameterListContext)
|
||||
params := w.parseNonEmptyParamList(nonEmptyParamList)
|
||||
f := &Function{
|
||||
Name: funcName,
|
||||
Params: params,
|
||||
}
|
||||
// Verify function name and param keys.
|
||||
if verifier != nil && !verifier(f, ctx) {
|
||||
return nil
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (w *Walker) ReportError(ctx interface{}, errorType ErrorType, target ...string) {
|
||||
//debug.PrintStack()
|
||||
bCtx := BaseContext(ctx)
|
||||
tgt := strconv.Quote(bCtx.GetStart().GetText())
|
||||
if len(target) != 0 {
|
||||
tgt = target[0]
|
||||
}
|
||||
if errorType == ErrorType_NotSet {
|
||||
w.parser.NotifyErrorListeners(fmt.Sprintf("%v %v.", tgt, errorType), nil, nil)
|
||||
return
|
||||
}
|
||||
w.parser.NotifyErrorListeners(fmt.Sprintf("%v %v.", tgt, errorType), bCtx.GetStart(), nil)
|
||||
}
|
||||
|
||||
func (w *Walker) parseDeclaration(ctx dae_config.IDeclarationContext) *Param {
|
||||
children := ctx.GetChildren()
|
||||
key := children[0].(*antlr.TerminalNodeImpl).GetText()
|
||||
switch valueCtx := children[2].(type) {
|
||||
case *dae_config.LiteralContext:
|
||||
value := getValueFromLiteral(valueCtx)
|
||||
return &Param{
|
||||
Key: key,
|
||||
Val: value,
|
||||
}
|
||||
case *dae_config.FunctionPrototypeExpressionContext:
|
||||
andFunctions := w.parseFunctionPrototypeExpression(valueCtx, nil)
|
||||
return &Param{
|
||||
Key: key,
|
||||
AndFunctions: andFunctions,
|
||||
}
|
||||
default:
|
||||
w.ReportError(valueCtx, ErrorType_Unsupported)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Walker) parseFunctionPrototypeExpression(ctx dae_config.IFunctionPrototypeExpressionContext, verifier functionVerifier) (andFunctions []*Function) {
|
||||
children := ctx.GetChildren()
|
||||
for _, child := range children {
|
||||
// And rules.
|
||||
if child, ok := child.(*dae_config.FunctionPrototypeContext); ok {
|
||||
function := w.parseFunctionPrototype(child, verifier)
|
||||
andFunctions = append(andFunctions, function)
|
||||
}
|
||||
}
|
||||
return andFunctions
|
||||
}
|
||||
|
||||
func (w *Walker) parseRoutingRule(ctx dae_config.IRoutingRuleContext) *RoutingRule {
|
||||
children := ctx.GetChildren()
|
||||
//logrus.Debugln(ctx.GetText(), children)
|
||||
left, ok := children[0].(*dae_config.RoutingRuleLeftContext)
|
||||
if !ok {
|
||||
w.ReportError(ctx, ErrorType_Unsupported, "not *RoutingRuleLeftContext: "+ctx.GetText())
|
||||
return nil
|
||||
}
|
||||
outbound := children[2].(*dae_config.Bare_literalContext).GetText()
|
||||
// Parse functions.
|
||||
children = left.GetChildren()
|
||||
functionList, ok := children[1].(*dae_config.FunctionPrototypeExpressionContext)
|
||||
if !ok {
|
||||
w.ReportError(ctx, ErrorType_Unsupported, "not *FunctionPrototypeExpressionContext: "+ctx.GetText())
|
||||
return nil
|
||||
}
|
||||
andFunctions := w.parseFunctionPrototypeExpression(functionList, nil)
|
||||
return &RoutingRule{
|
||||
AndFunctions: andFunctions,
|
||||
Outbound: outbound,
|
||||
}
|
||||
}
|
||||
|
||||
type routingRuleOrDeclarationOrLiteralOrExpressionListParser struct {
|
||||
Items []*Item
|
||||
Walker *Walker
|
||||
}
|
||||
|
||||
func (p *routingRuleOrDeclarationOrLiteralOrExpressionListParser) Parse(ctx dae_config.IRoutingRuleOrDeclarationOrLiteralOrExpressionListContext) {
|
||||
for _, elem := range ctx.GetChildren() {
|
||||
switch elem := elem.(type) {
|
||||
case dae_config.IRoutingRuleContext:
|
||||
rule := p.Walker.parseRoutingRule(elem)
|
||||
if rule == nil {
|
||||
return
|
||||
}
|
||||
p.Items = append(p.Items, NewRoutingRuleItem(rule))
|
||||
case dae_config.IDeclarationContext:
|
||||
param := p.Walker.parseDeclaration(elem)
|
||||
if param == nil {
|
||||
return
|
||||
}
|
||||
p.Items = append(p.Items, NewParamItem(param))
|
||||
case *dae_config.LiteralContext:
|
||||
p.Items = append(p.Items, NewParamItem(&Param{
|
||||
Key: "",
|
||||
Val: getValueFromLiteral(elem),
|
||||
}))
|
||||
case dae_config.IExpressionContext:
|
||||
section := p.Walker.parseExpression(elem)
|
||||
if section == nil {
|
||||
return
|
||||
}
|
||||
p.Items = append(p.Items, NewSectionItem(section))
|
||||
case dae_config.IRoutingRuleOrDeclarationOrLiteralOrExpressionListContext:
|
||||
p.Parse(elem)
|
||||
default:
|
||||
log.Printf("? %v", elem.(*dae_config.ExpressionContext))
|
||||
p.Walker.ReportError(elem, ErrorType_Unsupported)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
func (w *Walker) parseRoutingRuleOrDeclarationOrLiteralOrExpressionListContext(ctx dae_config.IRoutingRuleOrDeclarationOrLiteralOrExpressionListContext) []*Item {
|
||||
parser := routingRuleOrDeclarationOrLiteralOrExpressionListParser{
|
||||
Items: nil,
|
||||
Walker: w,
|
||||
}
|
||||
parser.Parse(ctx)
|
||||
return parser.Items
|
||||
|
||||
}
|
||||
|
||||
func (w *Walker) parseExpression(exp dae_config.IExpressionContext) *Section {
|
||||
children := exp.GetChildren()
|
||||
name := children[0].(*antlr.TerminalNodeImpl).GetText()
|
||||
list := children[2].(dae_config.IRoutingRuleOrDeclarationOrLiteralOrExpressionListContext)
|
||||
items := w.parseRoutingRuleOrDeclarationOrLiteralOrExpressionListContext(list)
|
||||
return &Section{
|
||||
Name: name,
|
||||
Items: items,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Walker) EnterProgramStructureBlcok(ctx *dae_config.ProgramStructureBlcokContext) {
|
||||
section := w.parseExpression(ctx.Expression())
|
||||
if section == nil {
|
||||
return
|
||||
}
|
||||
w.Sections = append(w.Sections, section)
|
||||
}
|
@ -3,11 +3,11 @@
|
||||
package geodata
|
||||
|
||||
import (
|
||||
_ "github.com/v2fly/v2ray-core/v5/common/protoext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
_ "github.com/v2rayA/dae/pkg/geodata/protoext"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
|
355
pkg/geodata/protoext/extensions.pb.go
Normal file
355
pkg/geodata/protoext/extensions.pb.go
Normal file
@ -0,0 +1,355 @@
|
||||
// Copied from https://github.com/v2fly/v2ray-core/tree/42b166760b2ba8d984e514b830fcd44e23728e43
|
||||
|
||||
package protoext
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
|
||||
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 MessageOpt struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Type []string `protobuf:"bytes,1,rep,name=type,proto3" json:"type,omitempty"`
|
||||
ShortName []string `protobuf:"bytes,2,rep,name=short_name,json=shortName,proto3" json:"short_name,omitempty"`
|
||||
TransportOriginalName string `protobuf:"bytes,86001,opt,name=transport_original_name,json=transportOriginalName,proto3" json:"transport_original_name,omitempty"`
|
||||
}
|
||||
|
||||
func (x *MessageOpt) Reset() {
|
||||
*x = MessageOpt{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_common_protoext_extensions_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *MessageOpt) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*MessageOpt) ProtoMessage() {}
|
||||
|
||||
func (x *MessageOpt) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_common_protoext_extensions_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 MessageOpt.ProtoReflect.Descriptor instead.
|
||||
func (*MessageOpt) Descriptor() ([]byte, []int) {
|
||||
return file_common_protoext_extensions_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *MessageOpt) GetType() []string {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *MessageOpt) GetShortName() []string {
|
||||
if x != nil {
|
||||
return x.ShortName
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *MessageOpt) GetTransportOriginalName() string {
|
||||
if x != nil {
|
||||
return x.TransportOriginalName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type FieldOpt struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
AnyWants []string `protobuf:"bytes,1,rep,name=any_wants,json=anyWants,proto3" json:"any_wants,omitempty"`
|
||||
AllowedValues []string `protobuf:"bytes,2,rep,name=allowed_values,json=allowedValues,proto3" json:"allowed_values,omitempty"`
|
||||
AllowedValueTypes []string `protobuf:"bytes,3,rep,name=allowed_value_types,json=allowedValueTypes,proto3" json:"allowed_value_types,omitempty"`
|
||||
// convert_time_read_file_into read a file into another field, and clear this field during input parsing
|
||||
ConvertTimeReadFileInto string `protobuf:"bytes,4,opt,name=convert_time_read_file_into,json=convertTimeReadFileInto,proto3" json:"convert_time_read_file_into,omitempty"`
|
||||
// forbidden marks a boolean to be inaccessible to user
|
||||
Forbidden bool `protobuf:"varint,5,opt,name=forbidden,proto3" json:"forbidden,omitempty"`
|
||||
// convert_time_resource_loading read a file, and place its resource hash into another field
|
||||
ConvertTimeResourceLoading string `protobuf:"bytes,6,opt,name=convert_time_resource_loading,json=convertTimeResourceLoading,proto3" json:"convert_time_resource_loading,omitempty"`
|
||||
// convert_time_parse_ip parse a string ip address, and put its binary representation into another field
|
||||
ConvertTimeParseIp string `protobuf:"bytes,7,opt,name=convert_time_parse_ip,json=convertTimeParseIp,proto3" json:"convert_time_parse_ip,omitempty"`
|
||||
}
|
||||
|
||||
func (x *FieldOpt) Reset() {
|
||||
*x = FieldOpt{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_common_protoext_extensions_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FieldOpt) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FieldOpt) ProtoMessage() {}
|
||||
|
||||
func (x *FieldOpt) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_common_protoext_extensions_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 FieldOpt.ProtoReflect.Descriptor instead.
|
||||
func (*FieldOpt) Descriptor() ([]byte, []int) {
|
||||
return file_common_protoext_extensions_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *FieldOpt) GetAnyWants() []string {
|
||||
if x != nil {
|
||||
return x.AnyWants
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FieldOpt) GetAllowedValues() []string {
|
||||
if x != nil {
|
||||
return x.AllowedValues
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FieldOpt) GetAllowedValueTypes() []string {
|
||||
if x != nil {
|
||||
return x.AllowedValueTypes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FieldOpt) GetConvertTimeReadFileInto() string {
|
||||
if x != nil {
|
||||
return x.ConvertTimeReadFileInto
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *FieldOpt) GetForbidden() bool {
|
||||
if x != nil {
|
||||
return x.Forbidden
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *FieldOpt) GetConvertTimeResourceLoading() string {
|
||||
if x != nil {
|
||||
return x.ConvertTimeResourceLoading
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *FieldOpt) GetConvertTimeParseIp() string {
|
||||
if x != nil {
|
||||
return x.ConvertTimeParseIp
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var file_common_protoext_extensions_proto_extTypes = []protoimpl.ExtensionInfo{
|
||||
{
|
||||
ExtendedType: (*descriptorpb.MessageOptions)(nil),
|
||||
ExtensionType: (*MessageOpt)(nil),
|
||||
Field: 50000,
|
||||
Name: "v2ray.core.common.protoext.message_opt",
|
||||
Tag: "bytes,50000,opt,name=message_opt",
|
||||
Filename: "common/protoext/extensions.proto",
|
||||
},
|
||||
{
|
||||
ExtendedType: (*descriptorpb.FieldOptions)(nil),
|
||||
ExtensionType: (*FieldOpt)(nil),
|
||||
Field: 50000,
|
||||
Name: "v2ray.core.common.protoext.field_opt",
|
||||
Tag: "bytes,50000,opt,name=field_opt",
|
||||
Filename: "common/protoext/extensions.proto",
|
||||
},
|
||||
}
|
||||
|
||||
// Extension fields to descriptorpb.MessageOptions.
|
||||
var (
|
||||
// optional v2ray.core.common.protoext.MessageOpt message_opt = 50000;
|
||||
E_MessageOpt = &file_common_protoext_extensions_proto_extTypes[0]
|
||||
)
|
||||
|
||||
// Extension fields to descriptorpb.FieldOptions.
|
||||
var (
|
||||
// optional v2ray.core.common.protoext.FieldOpt field_opt = 50000;
|
||||
E_FieldOpt = &file_common_protoext_extensions_proto_extTypes[1]
|
||||
)
|
||||
|
||||
var File_common_protoext_extensions_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_common_protoext_extensions_proto_rawDesc = []byte{
|
||||
0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78,
|
||||
0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x12, 0x1a, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x1a, 0x20,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
|
||||
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x22, 0x79, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x12, 0x12,
|
||||
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79,
|
||||
0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x12, 0x38, 0x0a, 0x17, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6f,
|
||||
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0xf1, 0x9f, 0x05,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f,
|
||||
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd0, 0x02, 0x0a, 0x08,
|
||||
0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x6e, 0x79, 0x5f,
|
||||
0x77, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x61, 0x6e, 0x79,
|
||||
0x57, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64,
|
||||
0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61,
|
||||
0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13,
|
||||
0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79,
|
||||
0x70, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77,
|
||||
0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x1b,
|
||||
0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x61,
|
||||
0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x17, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65,
|
||||
0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x74, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x6f,
|
||||
0x72, 0x62, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66,
|
||||
0x6f, 0x72, 0x62, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x1d, 0x63, 0x6f, 0x6e, 0x76,
|
||||
0x65, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||
0x65, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x1a, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x31, 0x0a, 0x15, 0x63,
|
||||
0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x73,
|
||||
0x65, 0x5f, 0x69, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6f, 0x6e, 0x76,
|
||||
0x65, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x73, 0x65, 0x49, 0x70, 0x3a, 0x6a,
|
||||
0x0a, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6f, 0x70, 0x74, 0x12, 0x1f, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd0,
|
||||
0x86, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x65, 0x78, 0x74, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x52, 0x0a,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x3a, 0x62, 0x0a, 0x09, 0x66, 0x69,
|
||||
0x65, 0x6c, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd0, 0x86, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
|
||||
0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2e, 0x46, 0x69, 0x65, 0x6c,
|
||||
0x64, 0x4f, 0x70, 0x74, 0x52, 0x08, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x42, 0x6f,
|
||||
0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74,
|
||||
0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76,
|
||||
0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f,
|
||||
0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65,
|
||||
0x78, 0x74, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e,
|
||||
0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x45, 0x78, 0x74, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_common_protoext_extensions_proto_rawDescOnce sync.Once
|
||||
file_common_protoext_extensions_proto_rawDescData = file_common_protoext_extensions_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_common_protoext_extensions_proto_rawDescGZIP() []byte {
|
||||
file_common_protoext_extensions_proto_rawDescOnce.Do(func() {
|
||||
file_common_protoext_extensions_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_protoext_extensions_proto_rawDescData)
|
||||
})
|
||||
return file_common_protoext_extensions_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_common_protoext_extensions_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_common_protoext_extensions_proto_goTypes = []interface{}{
|
||||
(*MessageOpt)(nil), // 0: v2ray.core.common.protoext.MessageOpt
|
||||
(*FieldOpt)(nil), // 1: v2ray.core.common.protoext.FieldOpt
|
||||
(*descriptorpb.MessageOptions)(nil), // 2: google.protobuf.MessageOptions
|
||||
(*descriptorpb.FieldOptions)(nil), // 3: google.protobuf.FieldOptions
|
||||
}
|
||||
var file_common_protoext_extensions_proto_depIdxs = []int32{
|
||||
2, // 0: v2ray.core.common.protoext.message_opt:extendee -> google.protobuf.MessageOptions
|
||||
3, // 1: v2ray.core.common.protoext.field_opt:extendee -> google.protobuf.FieldOptions
|
||||
0, // 2: v2ray.core.common.protoext.message_opt:type_name -> v2ray.core.common.protoext.MessageOpt
|
||||
1, // 3: v2ray.core.common.protoext.field_opt:type_name -> v2ray.core.common.protoext.FieldOpt
|
||||
4, // [4:4] is the sub-list for method output_type
|
||||
4, // [4:4] is the sub-list for method input_type
|
||||
2, // [2:4] is the sub-list for extension type_name
|
||||
0, // [0:2] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_common_protoext_extensions_proto_init() }
|
||||
func file_common_protoext_extensions_proto_init() {
|
||||
if File_common_protoext_extensions_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_common_protoext_extensions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*MessageOpt); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_common_protoext_extensions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*FieldOpt); 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_common_protoext_extensions_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 2,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_common_protoext_extensions_proto_goTypes,
|
||||
DependencyIndexes: file_common_protoext_extensions_proto_depIdxs,
|
||||
MessageInfos: file_common_protoext_extensions_proto_msgTypes,
|
||||
ExtensionInfos: file_common_protoext_extensions_proto_extTypes,
|
||||
}.Build()
|
||||
File_common_protoext_extensions_proto = out.File
|
||||
file_common_protoext_extensions_proto_rawDesc = nil
|
||||
file_common_protoext_extensions_proto_goTypes = nil
|
||||
file_common_protoext_extensions_proto_depIdxs = nil
|
||||
}
|
@ -19,6 +19,7 @@ func NewLogger(verbose int) *logrus.Logger {
|
||||
default:
|
||||
level = logrus.TraceLevel
|
||||
}
|
||||
|
||||
log.SetLevel(level)
|
||||
|
||||
return log
|
||||
|
Loading…
Reference in New Issue
Block a user