mirror of
https://github.com/luscis/openlan.git
synced 2025-09-26 20:41:29 +08:00
fea: access for ceci.
This commit is contained in:
16
Makefile
16
Makefile
@@ -106,20 +106,20 @@ docker-compose: ## create a compose files
|
||||
|
||||
ceci: linux-ceci darwin-ceci windows-ceci ## build all platform ceci
|
||||
|
||||
linux: env linux-access linux-switch linux-ceci linux-proxy ## build linux binary
|
||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan ./cmd/main.go
|
||||
linux: linux-access linux-switch linux-ceci linux-proxy ## build linux binary
|
||||
GOOS=linux go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan ./cmd/main.go
|
||||
|
||||
linux-access:
|
||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-access ./cmd/access
|
||||
GOOS=linux go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-access ./cmd/access
|
||||
|
||||
linux-switch:
|
||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-switch ./cmd/switch
|
||||
GOOS=linux go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-switch ./cmd/switch
|
||||
|
||||
linux-ceci:
|
||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openceci ./cmd/ceci
|
||||
GOOS=linux go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openceci ./cmd/ceci
|
||||
|
||||
linux-proxy:
|
||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-proxy ./cmd/proxy
|
||||
GOOS=linux go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-proxy ./cmd/proxy
|
||||
|
||||
linux-gzip: install ## build linux packages
|
||||
@rm -rf $(LIN_DIR).tar.gz
|
||||
@@ -148,7 +148,7 @@ install: env linux ## install packages
|
||||
@echo "Installed to $(LIN_DIR)"
|
||||
|
||||
## cross build for windows
|
||||
windows: env windows-ceci ## build windows binary
|
||||
windows: windows-ceci ## build windows binary
|
||||
|
||||
windows-ceci:
|
||||
GOOS=windows GOARCH=amd64 go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openceci.exe ./cmd/ceci
|
||||
@@ -163,7 +163,7 @@ windows-gzip: env windows ## build windows packages
|
||||
## cross build for osx
|
||||
osx: darwin
|
||||
|
||||
darwin: env darwin-ceci ## build darwin binary
|
||||
darwin: darwin-ceci ## build darwin binary
|
||||
|
||||
darwin-ceci:
|
||||
GOOS=darwin GOARCH=amd64 go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openceci.dar ./cmd/ceci
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
//go:build linux
|
||||
|
||||
package main
|
||||
|
||||
@@ -16,8 +16,10 @@ func main() {
|
||||
if c.Terminal == "off" {
|
||||
libol.PreNotify()
|
||||
}
|
||||
|
||||
p.Initialize()
|
||||
libol.Go(p.Start)
|
||||
|
||||
if c.Terminal == "on" {
|
||||
t := access.NewTerminal(p)
|
||||
t.Start()
|
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/luscis/openlan/pkg/access"
|
||||
"github.com/luscis/openlan/pkg/config"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/proxy"
|
||||
@@ -11,7 +12,7 @@ import (
|
||||
func main() {
|
||||
mode := "http"
|
||||
conf := ""
|
||||
flag.StringVar(&mode, "mode", "http", "Proxy mode for http, socks or tcp")
|
||||
flag.StringVar(&mode, "mode", "http", "Proxy mode for http, socks, tcp and access")
|
||||
flag.StringVar(&conf, "conf", "ceci.yaml", "The configuration file")
|
||||
flag.Parse()
|
||||
|
||||
@@ -30,13 +31,25 @@ func main() {
|
||||
}
|
||||
p := proxy.NewSocksProxy(c)
|
||||
libol.Go(p.Start)
|
||||
} else {
|
||||
} else if mode == "tcp" {
|
||||
c := &config.TcpProxy{Conf: conf}
|
||||
if err := c.Initialize(); err != nil {
|
||||
return
|
||||
}
|
||||
p := proxy.NewTcpProxy(c)
|
||||
libol.Go(p.Start)
|
||||
} else if mode == "access" {
|
||||
c := &config.Point{
|
||||
RequestAddr: true,
|
||||
Terminal: "off",
|
||||
Conf: conf,
|
||||
}
|
||||
if err := c.Initialize(); err != nil {
|
||||
return
|
||||
}
|
||||
p := access.NewPoint(c)
|
||||
p.Initialize()
|
||||
libol.Go(p.Start)
|
||||
}
|
||||
libol.SdNotify()
|
||||
libol.Wait()
|
||||
|
35
go.mod
35
go.mod
@@ -1,16 +1,8 @@
|
||||
module github.com/luscis/openlan
|
||||
|
||||
go 1.22.0
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.0
|
||||
|
||||
replace (
|
||||
github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.8.1
|
||||
golang.org/x/crypto => github.com/golang/crypto v0.0.0-20200604202706-70a84ac30bf9
|
||||
golang.org/x/net => github.com/golang/net v0.0.0-20190812203447-cdfb69ac37fc
|
||||
golang.org/x/sys => github.com/golang/sys v0.0.0-20190209173611-3b5209105503
|
||||
golang.org/x/time => github.com/golang/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||
)
|
||||
replace github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.8.1
|
||||
|
||||
exclude github.com/sirupsen/logrus v1.8.1
|
||||
|
||||
@@ -19,38 +11,29 @@ require (
|
||||
github.com/coreos/go-systemd/v22 v22.3.2
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/go-ldap/ldap v3.0.3+incompatible
|
||||
github.com/go-logr/logr v1.1.0
|
||||
github.com/go-logr/stdr v1.1.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/miekg/dns v1.1.65
|
||||
github.com/moby/libnetwork v0.5.6
|
||||
github.com/ovn-org/libovsdb v0.6.1-0.20220127023511-a619f0fd93be
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.1.5
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
github.com/xtaci/kcp-go/v5 v5.6.1
|
||||
golang.org/x/net v0.35.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/sys v0.32.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Sirupsen/logrus v0.0.0-00010101000000-000000000000 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||
github.com/cenkalti/hub v1.0.1 // indirect
|
||||
github.com/cenkalti/rpc2 v0.0.0-20210604223624-c1acbc6ec984 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/chzyer/logex v1.2.0 // indirect
|
||||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23 // indirect
|
||||
github.com/chzyer/test v1.0.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/libnetwork v0.5.6 // indirect
|
||||
github.com/godbus/dbus v4.1.0+incompatible // indirect
|
||||
github.com/golang/protobuf v1.5.0 // indirect
|
||||
github.com/google/uuid v1.2.0 // indirect
|
||||
github.com/golang/protobuf v1.4.3 // indirect
|
||||
github.com/klauspost/cpuid v1.3.1 // indirect
|
||||
github.com/klauspost/reedsolomon v1.9.9 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
@@ -60,19 +43,17 @@ require (
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/templexxx/cpu v0.0.7 // indirect
|
||||
github.com/templexxx/xorsimd v0.4.1 // indirect
|
||||
github.com/tjfoc/gmsm v1.3.2 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/mod v0.23.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/tools v0.30.0 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
google.golang.org/protobuf v1.26.0-rc.1 // indirect
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
)
|
||||
|
129
go.sum
129
go.sum
@@ -1,8 +1,5 @@
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -12,43 +9,23 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/cenk/hub v1.0.1 h1:RBwXNOF4a8KjD8BJ08XqN8KbrqaGiQLDrgvUGJSHuPA=
|
||||
github.com/cenk/hub v1.0.1/go.mod h1:rJM1LNAW0ppT8FMMuPK6c2NP/R2nH/UthtuRySSaf6Y=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cenkalti/hub v1.0.1 h1:UMtjc6dHSaOQTO15SVA50MBIR9zQwvsukQupDrkIRtg=
|
||||
github.com/cenkalti/hub v1.0.1/go.mod h1:tcYwtS3a2d9NO/0xDXVJWx3IedurUjYCqFCmpi0lpHs=
|
||||
github.com/cenkalti/rpc2 v0.0.0-20210604223624-c1acbc6ec984 h1:CNwZyGS6KpfaOWbh2yLkSy3rSTUh3jub9CzpFpP6PVQ=
|
||||
github.com/cenkalti/rpc2 v0.0.0-20210604223624-c1acbc6ec984/go.mod h1:v2npkhrXyk5BCnkNIiPdRI23Uq6uWPUQGL2hnRcRr/M=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||
github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM=
|
||||
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
|
||||
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23 h1:dZ0/VyGgQdVGAss6Ju0dt5P0QltE0SFY5Woh6hbIfiQ=
|
||||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
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=
|
||||
github.com/docker/cli v20.10.8+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/libnetwork v0.5.6 h1:hnGiypBsZR6PW1I8lqaBHh06U6LCJbI3IhOvfsZiymY=
|
||||
github.com/docker/libnetwork v0.5.6/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
@@ -59,20 +36,11 @@ github.com/go-ldap/ldap v3.0.3+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v1.1.0 h1:nAbevmWlS2Ic4m4+/An5NXkaGqlqpbBgdcuThZxnZyI=
|
||||
github.com/go-logr/logr v1.1.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/stdr v1.1.0 h1:WSypkOvL7AfqHep42aGGLagyxUjJCQFFs/2nIitlVTQ=
|
||||
github.com/go-logr/stdr v1.1.0/go.mod h1:Xff/PTSzmJ+zDsu/KDy4l6Axizfso1w7QcxLnWTdto4=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
|
||||
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:lIQUCEYYutFXVbIXlWWJUOtinadHOl9N6P84tMjXLQU=
|
||||
github.com/golang/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
github.com/golang/net v0.0.0-20190812203447-cdfb69ac37fc h1:ANlSYw21rkVMLEZGosY7p2hFSi/JitYbABaYmw7Tv4A=
|
||||
github.com/golang/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:98y8FxUyMjTdJ5eOj/8vzuiVO14/dkJ98NYhEPG8QGY=
|
||||
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=
|
||||
@@ -82,11 +50,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/sys v0.0.0-20190209173611-3b5209105503 h1:KkzKRheGyjoZo7gN0XfHPvHPiigTohQEshRskFvbq6s=
|
||||
github.com/golang/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:5JyrLPvD/ZdaYkT7IqKhsP5xt7aLjA99KXRtk4EIYDk=
|
||||
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=
|
||||
@@ -95,61 +60,42 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||
github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54=
|
||||
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc=
|
||||
github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
|
||||
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
|
||||
github.com/moby/libnetwork v0.5.6 h1:pDuZwsc3ViMrIi0i4vrTtsgBN1+8ReJY6vAGnDCZ8AI=
|
||||
github.com/moby/libnetwork v0.5.6/go.mod h1:RQTqDxGZChsPHosY8R3ZL2THYWUuW8X5SRhiBNoTY5I=
|
||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||
github.com/ory/dockertest/v3 v3.8.0/go.mod h1:9zPATATlWQru+ynXP+DytBQrsXV7Tmlx7K86H6fQaDo=
|
||||
github.com/ovn-org/libovsdb v0.6.1-0.20220127023511-a619f0fd93be h1:U8WVtNNTfBKj/5OE3uBe57oNJ+x5KSMl+3hM7iLSbdk=
|
||||
github.com/ovn-org/libovsdb v0.6.1-0.20220127023511-a619f0fd93be/go.mod h1:aLvY7gPs/vLyJXF+PpZzvWlR5LB4QNJvBYIQMskJLZk=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -174,25 +120,16 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.1.5 h1:PDSQv9y2S85Fl7VBeOMF9StzeXZyK1HakRm86CUbr28=
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.1.5/go.mod h1:AGGpIoek4HRno4xzyFiAtLHkOpcoznZEkAccaI/rplM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
@@ -201,7 +138,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||
github.com/templexxx/cpu v0.0.7 h1:pUEZn8JBy/w5yzdYWgx+0m0xL9uk6j4K91C5kOViAzo=
|
||||
github.com/templexxx/cpu v0.0.7/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||
@@ -209,47 +145,73 @@ github.com/templexxx/xorsimd v0.4.1 h1:iUZcywbOYDRAZUasAs2eSCUW8eobuZDy0I9FJiORk
|
||||
github.com/templexxx/xorsimd v0.4.1/go.mod h1:W+ffZz8jJMH2SXwuKu9WhygqBMbFnp14G2fqEr8qaNo=
|
||||
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
|
||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xtaci/kcp-go/v5 v5.6.1 h1:Pwn0aoeNSPF9dTS7IgiPXn0HEtaIlVb6y5UKWPsx8bI=
|
||||
github.com/xtaci/kcp-go/v5 v5.6.1/go.mod h1:W3kVPyNYwZ06p79dNwFWQOVFrdcBpDBsdyvK8moQrYo=
|
||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
|
||||
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=
|
||||
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
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.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
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.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
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-20190423024810-112230192c58/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-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/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -263,9 +225,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||
@@ -282,6 +243,4 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
20
pkg/access/point_others.go
Normal file
20
pkg/access/point_others.go
Normal file
@@ -0,0 +1,20 @@
|
||||
//go:build !linux && !windows && !darwin
|
||||
|
||||
package access
|
||||
|
||||
import "github.com/luscis/openlan/pkg/config"
|
||||
|
||||
type Point struct {
|
||||
}
|
||||
|
||||
func NewPoint(config *config.Point) *Point {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Point) Initialize() {
|
||||
|
||||
}
|
||||
|
||||
func (p *Point) Start() {
|
||||
|
||||
}
|
@@ -1,9 +1,10 @@
|
||||
package access
|
||||
|
||||
import (
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/songgao/water"
|
||||
"testing"
|
||||
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/water"
|
||||
)
|
||||
|
||||
func TestTapWrite(t *testing.T) {
|
||||
|
@@ -34,7 +34,7 @@ type Point struct {
|
||||
PProf string `json:"pprof,omitempty"`
|
||||
RequestAddr bool `json:"requestAddr"`
|
||||
ByPass bool `json:"bypass,omitempty"`
|
||||
SaveFile string `json:"-"`
|
||||
Conf string `json:"-"`
|
||||
Queue *Queue `json:"queue,omitempty"`
|
||||
Terminal string `json:"-"`
|
||||
Cert *Cert `json:"cert,omitempty"`
|
||||
@@ -69,7 +69,7 @@ func (ap *Point) Parse() {
|
||||
flag.StringVar(&ap.Alias, "alias", "", "Alias for this point")
|
||||
flag.StringVar(&ap.Log.File, "log:file", "", "File log saved to")
|
||||
flag.StringVar(&ap.Terminal, "terminal", "", "Run interactive terminal")
|
||||
flag.StringVar(&ap.SaveFile, "conf", "", "The configuration file")
|
||||
flag.StringVar(&ap.Conf, "conf", "", "The configuration file")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
@@ -77,12 +77,14 @@ func (ap *Point) Id() string {
|
||||
return ap.Connection + ":" + ap.Network
|
||||
}
|
||||
|
||||
func (ap *Point) Initialize() {
|
||||
func (ap *Point) Initialize() error {
|
||||
if err := ap.Load(); err != nil {
|
||||
libol.Warn("NewPoint.Initialize %s", err)
|
||||
return err
|
||||
}
|
||||
ap.Correct()
|
||||
libol.SetLogger(ap.Log.File, ap.Log.Verbose)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ap *Point) Correct() {
|
||||
@@ -128,8 +130,8 @@ func (ap *Point) Correct() {
|
||||
}
|
||||
|
||||
func (ap *Point) Load() error {
|
||||
if err := libol.FileExist(ap.SaveFile); err == nil {
|
||||
return libol.UnmarshalLoad(ap, ap.SaveFile)
|
||||
if err := libol.FileExist(ap.Conf); err == nil {
|
||||
return libol.UnmarshalLoad(ap, ap.Conf)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -2,10 +2,11 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPointFlags(t *testing.T) {
|
||||
@@ -19,7 +20,7 @@ func TestPointFlags(t *testing.T) {
|
||||
ap.Parse()
|
||||
fmt.Println(ap)
|
||||
assert.Equal(t, "fake", ap.Alias, "be the same.")
|
||||
assert.Equal(t, "/etc/openlan/fake.json", ap.SaveFile, "be the same.")
|
||||
assert.Equal(t, "/etc/openlan/fake.json", ap.Conf, "be the same.")
|
||||
assert.Equal(t, "off", ap.Terminal, "be the same.")
|
||||
}
|
||||
|
||||
|
@@ -8,16 +8,6 @@ import (
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
)
|
||||
|
||||
type ShadowProxy struct {
|
||||
Server string `json:"server,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
Cipher string `json:"cipher,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
Plugin string `json:"plugin,omitempty"`
|
||||
PluginOpts string `json:"pluginOpts,omitempty"`
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
}
|
||||
|
||||
type SocksProxy struct {
|
||||
Conf string `json:"-" yaml:"-"`
|
||||
ConfDir string `json:"-" yaml:"-"`
|
||||
@@ -185,14 +175,13 @@ func (t *TcpProxy) Load() error {
|
||||
}
|
||||
|
||||
type Proxy struct {
|
||||
Conf string `json:"-" yaml:"-"`
|
||||
ConfDir string `json:"-" yaml:"-"`
|
||||
Log Log `json:"log"`
|
||||
Socks []*SocksProxy `json:"socks,omitempty" yaml:"socks,omitempty"`
|
||||
Http []*HttpProxy `json:"http,omitempty" yaml:"http,omitempty"`
|
||||
Tcp []*TcpProxy `json:"tcp,omitempty" yaml:"tcp,omitempty"`
|
||||
Shadow []*ShadowProxy `json:"shadow,omitempty" yaml:"shadow,omitempty"`
|
||||
PProf string `json:"pprof,omitempty" yaml:"pprof,omitempty"`
|
||||
Conf string `json:"-" yaml:"-"`
|
||||
ConfDir string `json:"-" yaml:"-"`
|
||||
Log Log `json:"log"`
|
||||
Socks []*SocksProxy `json:"socks,omitempty" yaml:"socks,omitempty"`
|
||||
Http []*HttpProxy `json:"http,omitempty" yaml:"http,omitempty"`
|
||||
Tcp []*TcpProxy `json:"tcp,omitempty" yaml:"tcp,omitempty"`
|
||||
PProf string `json:"pprof,omitempty" yaml:"pprof,omitempty"`
|
||||
}
|
||||
|
||||
func NewProxy() *Proxy {
|
||||
|
@@ -1,151 +0,0 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/go-logr/stdr"
|
||||
"github.com/luscis/openlan/cmd/api"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/ovn-org/libovsdb/cache"
|
||||
"github.com/ovn-org/libovsdb/client"
|
||||
"github.com/ovn-org/libovsdb/model"
|
||||
"github.com/ovn-org/libovsdb/ovsdb"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
type OvSDB struct {
|
||||
client.Client
|
||||
Ops []ovsdb.Operation
|
||||
}
|
||||
|
||||
func (o *OvSDB) Context() context.Context {
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
func (o *OvSDB) Switch() (*Switch, error) {
|
||||
var listSw []Switch
|
||||
if err := o.List(&listSw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(listSw) == 0 {
|
||||
return nil, libol.NewErr("hasn't switch")
|
||||
}
|
||||
return &listSw[0], nil
|
||||
}
|
||||
|
||||
func (o *OvSDB) Execute(ops []ovsdb.Operation) {
|
||||
o.Ops = append(o.Ops, ops...)
|
||||
}
|
||||
|
||||
func (o *OvSDB) Commit() ([]ovsdb.OperationResult, error) {
|
||||
ops := o.Ops
|
||||
o.Ops = nil
|
||||
return o.Client.Transact(o.Context(), ops...)
|
||||
}
|
||||
|
||||
func (o *OvSDB) Get(m model.Model) error {
|
||||
return o.Client.Get(o.Context(), m)
|
||||
}
|
||||
|
||||
func (o *OvSDB) Transact(ops ...ovsdb.Operation) ([]ovsdb.OperationResult, error) {
|
||||
return o.Client.Transact(o.Context(), ops...)
|
||||
}
|
||||
|
||||
func (o *OvSDB) List(result interface{}) error {
|
||||
return o.Client.List(o.Context(), result)
|
||||
}
|
||||
|
||||
func (o *OvSDB) WhereList(predict interface{}, result interface{}) error {
|
||||
cache := o.Client.WhereCache(predict)
|
||||
if cache == nil {
|
||||
return libol.NewErr("not cache list")
|
||||
}
|
||||
return cache.List(o.Context(), result)
|
||||
}
|
||||
|
||||
type DBClient struct {
|
||||
Server string
|
||||
Database string
|
||||
Verbose bool
|
||||
Client *OvSDB
|
||||
}
|
||||
|
||||
func (c *DBClient) Context() context.Context {
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
func (c *DBClient) NilLog() *logr.Logger {
|
||||
// create a new logger to log to /dev/null
|
||||
writer, err := libol.OpenWrite(os.DevNull)
|
||||
if err != nil {
|
||||
writer = os.Stderr
|
||||
}
|
||||
l := stdr.NewWithOptions(log.New(writer, "", log.LstdFlags), stdr.Options{LogCaller: stdr.All})
|
||||
return &l
|
||||
}
|
||||
|
||||
func (c *DBClient) Open(handler *cache.EventHandlerFuncs, block func(val *DBClient)) error {
|
||||
server := c.Server
|
||||
database := c.Database
|
||||
dbModel, err := model.NewClientDBModel(database, models)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ops := []client.Option{
|
||||
client.WithEndpoint(server),
|
||||
}
|
||||
if !c.Verbose {
|
||||
ops = append(ops, client.WithLogger(c.NilLog()))
|
||||
}
|
||||
ovs, err := client.NewOVSDBClient(dbModel, ops...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ovs.Connect(c.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
c.Client = &OvSDB{Client: ovs}
|
||||
if block != nil {
|
||||
block(c)
|
||||
}
|
||||
if handler != nil {
|
||||
processor := ovs.Cache()
|
||||
if processor == nil {
|
||||
return libol.NewErr("can't get cache.")
|
||||
}
|
||||
processor.AddEventHandler(handler)
|
||||
}
|
||||
if _, err := ovs.MonitorAll(c.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var Conf *DBClient
|
||||
var Client *OvSDB
|
||||
|
||||
func NewConfClient(handler *cache.EventHandlerFuncs) (*DBClient, error) {
|
||||
var err error
|
||||
if Conf == nil {
|
||||
obj := &DBClient{
|
||||
Server: api.Server,
|
||||
Database: api.Database,
|
||||
Verbose: api.Verbose,
|
||||
}
|
||||
err = obj.Open(handler, func(val *DBClient) {
|
||||
Conf = val
|
||||
Client = val.Client
|
||||
})
|
||||
}
|
||||
return Conf, err
|
||||
}
|
||||
|
||||
func NewClient(handler *cache.EventHandlerFuncs) (*DBClient, error) {
|
||||
obj := &DBClient{
|
||||
Server: api.Server,
|
||||
Database: api.Database,
|
||||
Verbose: api.Verbose,
|
||||
}
|
||||
return obj, obj.Open(handler, nil)
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/ovn-org/libovsdb/model"
|
||||
)
|
||||
|
||||
var models = map[string]model.Model{
|
||||
"Global_Switch": &Switch{},
|
||||
"Virtual_Network": &VirtualNetwork{},
|
||||
"Virtual_Link": &VirtualLink{},
|
||||
"Open_VPN": &OpenVPN{},
|
||||
"Name_Cache": &NameCache{},
|
||||
"Prefix_Route": &PrefixRoute{},
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Switch struct {
|
||||
UUID string `ovsdb:"_uuid" json:"uuid"`
|
||||
Protocol string `ovsdb:"protocol" json:"protocol"`
|
||||
Listen int `ovsdb:"listen" json:"listen"`
|
||||
OtherConfig map[string]string `ovsdb:"other_config" json:"other_config"`
|
||||
VirtualNetworks []string `ovsdb:"virtual_networks" json:"virtual_networks"`
|
||||
}
|
||||
|
||||
type VirtualNetwork struct {
|
||||
UUID string `ovsdb:"_uuid" json:"uuid"`
|
||||
Name string `ovsdb:"name" json:"name"`
|
||||
Provider string `ovsdb:"provider" json:"provider"`
|
||||
Bridge string `ovsdb:"bridge" json:"bridge"`
|
||||
Address string `ovsdb:"address" json:"address"`
|
||||
OtherConfig map[string]string `ovsdb:"other_config" json:"other_config"`
|
||||
RemoteLinks []string `ovsdb:"remote_links" json:"remote_links"`
|
||||
LocalLinks []string `ovsdb:"local_links" json:"local_links"`
|
||||
OpenVPN *string `ovsdb:"open_vpn" json:"open_vpn"`
|
||||
PrefixRoutes []string `ovsdb:"prefix_routes" json:"prefix_routes"`
|
||||
}
|
||||
|
||||
type VirtualLink struct {
|
||||
UUID string `ovsdb:"_uuid" json:"uuid"`
|
||||
Network string `ovsdb:"network" json:"network"`
|
||||
Connection string `ovsdb:"connection" json:"connection"`
|
||||
Device string `ovsdb:"device" json:"device"`
|
||||
OtherConfig map[string]string `ovsdb:"other_config" json:"other_config"`
|
||||
Authentication map[string]string `ovsdb:"authentication" json:"authentication"`
|
||||
LinkState string `ovsdb:"link_state" json:"link_state"`
|
||||
Status map[string]string `ovsdb:"status" json:"status"`
|
||||
}
|
||||
|
||||
func (l *VirtualLink) IsUdpIn() bool {
|
||||
if HasPrefix(l.Device, 4, "spi:") &&
|
||||
HasPrefix(l.Connection, 4, "udp:") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (l *VirtualLink) Spi() uint32 {
|
||||
spi, _ := strconv.Atoi(l.Device[4:])
|
||||
return uint32(spi)
|
||||
}
|
||||
|
||||
type OpenVPN struct {
|
||||
UUID string `ovsdb:"_uuid" json:"uuid"`
|
||||
Protocol string `ovsdb:"protocol" json:"protocol"`
|
||||
Listen int `ovsdb:"listen" json:"listen"`
|
||||
}
|
||||
|
||||
type NameCache struct {
|
||||
UUID string `ovsdb:"_uuid" json:"uuid"`
|
||||
Name string `ovsdb:"name" json:"name"`
|
||||
Address string `ovsdb:"address" json:"address"`
|
||||
UpdateAt string `ovsdb:"update_at" json:"update_at"`
|
||||
}
|
||||
|
||||
type PrefixRoute struct {
|
||||
UUID string `ovsdb:"_uuid" json:"uuid"`
|
||||
Network string `ovsdb:"network" json:"network"`
|
||||
Prefix string `ovsdb:"prefix" json:"prefix"`
|
||||
Source string `ovsdb:"source" json:"source"`
|
||||
Gateway string `ovsdb:"gateway" json:"gateway"`
|
||||
Mode string `ovsdb:"mode" json:"mode"`
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/ovn-org/libovsdb/ovsdb"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func PrintError(result []ovsdb.OperationResult) {
|
||||
for _, ret := range result {
|
||||
if len(ret.Error) == 0 {
|
||||
continue
|
||||
}
|
||||
libol.Info("%s", ret.Details)
|
||||
}
|
||||
}
|
||||
|
||||
func GenUUID() string {
|
||||
return libol.GenString(32)
|
||||
}
|
||||
|
||||
func HasPrefix(value string, index int, dest string) bool {
|
||||
if len(value) >= index {
|
||||
return value[:index] == dest
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetAddrPort(conn string) (string, int) {
|
||||
values := strings.SplitN(conn, ":", 2)
|
||||
if len(values) == 2 {
|
||||
port, _ := strconv.Atoi(values[1])
|
||||
return values[0], port
|
||||
}
|
||||
return values[0], 0
|
||||
}
|
@@ -8,6 +8,10 @@ import (
|
||||
nl "github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func NewBridger(provider, name string, ifMtu int) Bridger {
|
||||
return NewLinuxBridge(name, ifMtu)
|
||||
}
|
||||
|
||||
type LinuxBridge struct {
|
||||
sts DeviceStats
|
||||
address *nl.Addr
|
||||
|
81
pkg/network/bridge_others.go
Normal file
81
pkg/network/bridge_others.go
Normal file
@@ -0,0 +1,81 @@
|
||||
//go:build !linux
|
||||
|
||||
package network
|
||||
|
||||
type OtherBridge struct {
|
||||
name string
|
||||
mtu int
|
||||
}
|
||||
|
||||
func NewBridger(provider, name string, ifMtu int) Bridger {
|
||||
return &OtherBridge{
|
||||
name: name,
|
||||
mtu: ifMtu,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *OtherBridge) Type() string {
|
||||
return "NAN"
|
||||
}
|
||||
|
||||
func (b *OtherBridge) Name() string {
|
||||
return b.name
|
||||
}
|
||||
func (b *OtherBridge) Open(addr string) {
|
||||
}
|
||||
|
||||
func (b *OtherBridge) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OtherBridge) AddSlave(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OtherBridge) DelSlave(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OtherBridge) ListSlave() <-chan Taper {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OtherBridge) Mtu() int {
|
||||
return b.mtu
|
||||
}
|
||||
|
||||
func (b *OtherBridge) Stp(enable bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OtherBridge) Delay(value int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OtherBridge) Kernel() string {
|
||||
return "NAN"
|
||||
}
|
||||
|
||||
func (b *OtherBridge) ListMac() <-chan *MacFdb {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OtherBridge) String() string {
|
||||
return "NAN"
|
||||
}
|
||||
|
||||
func (b *OtherBridge) Stats() DeviceStats {
|
||||
return DeviceStats{}
|
||||
}
|
||||
|
||||
func (b *OtherBridge) CallIptables(value int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OtherBridge) L3Name() string {
|
||||
return "NAN"
|
||||
}
|
||||
|
||||
func (b *OtherBridge) SetMtu(mtu int) error {
|
||||
return nil
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
package network
|
||||
|
||||
func NewBridger(provider, name string, ifMtu int) Bridger {
|
||||
return NewLinuxBridge(name, ifMtu)
|
||||
}
|
@@ -1,9 +1,10 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/songgao/water"
|
||||
"sync"
|
||||
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/water"
|
||||
)
|
||||
|
||||
type KernelTap struct {
|
||||
|
@@ -1,200 +0,0 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type VirtualTap struct {
|
||||
lock sync.RWMutex
|
||||
kernC int
|
||||
kernQ chan []byte
|
||||
virtC int
|
||||
virtQ chan []byte
|
||||
master Bridger
|
||||
tenant string
|
||||
flags uint
|
||||
cfg TapConfig
|
||||
name string
|
||||
ifMtu int
|
||||
sts DeviceStats
|
||||
}
|
||||
|
||||
func NewVirtualTap(tenant string, c TapConfig) (*VirtualTap, error) {
|
||||
name := c.Name
|
||||
if name == "" {
|
||||
name = Taps.GenName()
|
||||
}
|
||||
tap := &VirtualTap{
|
||||
cfg: c,
|
||||
tenant: tenant,
|
||||
name: name,
|
||||
ifMtu: 1514,
|
||||
}
|
||||
Taps.Add(tap)
|
||||
return tap, nil
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Type() string {
|
||||
return ProviderVir
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Tenant() string {
|
||||
return t.tenant
|
||||
}
|
||||
|
||||
func (t *VirtualTap) IsTun() bool {
|
||||
return t.cfg.Type == TUN
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Name() string {
|
||||
return t.name
|
||||
}
|
||||
|
||||
func (t *VirtualTap) hasFlags(v uint) bool {
|
||||
return t.flags&v == v
|
||||
}
|
||||
|
||||
func (t *VirtualTap) setFlags(v uint) {
|
||||
t.flags |= v
|
||||
}
|
||||
|
||||
func (t *VirtualTap) clearFlags(v uint) {
|
||||
t.flags &= ^v
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Has(v uint) bool {
|
||||
t.lock.RLock()
|
||||
defer t.lock.RUnlock()
|
||||
return t.hasFlags(v)
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Write(p []byte) (int, error) {
|
||||
if libol.HasLog(libol.DEBUG) {
|
||||
libol.Debug("VirtualTap.Write: %s % x", t, p[:20])
|
||||
}
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
if !t.hasFlags(UsUp) {
|
||||
return 0, libol.NewErr("notUp")
|
||||
}
|
||||
if t.virtC >= t.cfg.VirBuf {
|
||||
libol.Warn("VirtualTap.Write: buffer fully")
|
||||
t.sts.Drop++
|
||||
return 0, nil
|
||||
}
|
||||
t.virtC++
|
||||
t.virtQ <- p
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Read(p []byte) (int, error) {
|
||||
t.lock.Lock()
|
||||
if !t.hasFlags(UsUp) {
|
||||
t.lock.Unlock()
|
||||
return 0, libol.NewErr("notUp")
|
||||
}
|
||||
t.lock.Unlock()
|
||||
data := <-t.kernQ
|
||||
t.lock.Lock()
|
||||
t.kernC--
|
||||
t.lock.Unlock()
|
||||
return copy(p, data), nil
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Recv(p []byte) (int, error) {
|
||||
t.lock.Lock()
|
||||
if !t.hasFlags(UsUp) {
|
||||
t.lock.Unlock()
|
||||
return 0, libol.NewErr("notUp")
|
||||
}
|
||||
t.lock.Unlock()
|
||||
data := <-t.virtQ
|
||||
t.lock.Lock()
|
||||
t.virtC--
|
||||
t.lock.Unlock()
|
||||
return copy(p, data), nil
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Send(p []byte) (int, error) {
|
||||
if libol.HasLog(libol.DEBUG) {
|
||||
libol.Debug("VirtualTap.Send: %s % x", t, p[:20])
|
||||
}
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
if !t.hasFlags(UsUp) {
|
||||
return 0, libol.NewErr("notUp")
|
||||
}
|
||||
if t.kernC >= t.cfg.KernBuf {
|
||||
t.sts.Drop++
|
||||
libol.Warn("VirtualTap.Send: buffer fully")
|
||||
return 0, nil
|
||||
}
|
||||
t.kernC++
|
||||
t.kernQ <- p
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Close() error {
|
||||
t.Down()
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
if t.hasFlags(UsClose) {
|
||||
return nil
|
||||
}
|
||||
t.setFlags(UsClose)
|
||||
t.clearFlags(UsUp)
|
||||
if t.master != nil {
|
||||
_ = t.master.DelSlave(t.name)
|
||||
t.master = nil
|
||||
}
|
||||
Taps.Del(t.name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Master() Bridger {
|
||||
t.lock.RLock()
|
||||
defer t.lock.RUnlock()
|
||||
return t.master
|
||||
}
|
||||
|
||||
func (t *VirtualTap) SetMaster(dev Bridger) error {
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
if t.master == nil {
|
||||
t.master = dev
|
||||
}
|
||||
return libol.NewErr("already to %s", t.master)
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Up() {
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
if !t.hasFlags(UsUp) {
|
||||
t.kernC = 0
|
||||
t.kernQ = make(chan []byte, t.cfg.KernBuf)
|
||||
t.virtC = 0
|
||||
t.virtQ = make(chan []byte, t.cfg.VirBuf)
|
||||
t.setFlags(UsUp)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Down() {
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
if t.hasFlags(UsUp) {
|
||||
t.clearFlags(UsUp)
|
||||
close(t.kernQ)
|
||||
t.kernQ = nil
|
||||
close(t.virtQ)
|
||||
t.virtQ = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *VirtualTap) String() string {
|
||||
return t.name
|
||||
}
|
||||
|
||||
func (t *VirtualTap) Mtu() int {
|
||||
return t.ifMtu
|
||||
}
|
@@ -38,9 +38,6 @@ type Taper interface {
|
||||
}
|
||||
|
||||
func NewTaper(tenant string, c TapConfig) (Taper, error) {
|
||||
if c.Provider == ProviderVir {
|
||||
return NewVirtualTap(tenant, c)
|
||||
}
|
||||
return NewKernelTap(tenant, c)
|
||||
}
|
||||
|
||||
|
20
pkg/network/vrf_others.go
Normal file
20
pkg/network/vrf_others.go
Normal file
@@ -0,0 +1,20 @@
|
||||
//go:build !linux
|
||||
|
||||
package network
|
||||
|
||||
type VRF struct {
|
||||
name string
|
||||
table int
|
||||
}
|
||||
|
||||
func NewVRF(name string, table int) *VRF {
|
||||
return &VRF{}
|
||||
}
|
||||
|
||||
func (v *VRF) Table() int {
|
||||
return v.table
|
||||
}
|
||||
|
||||
func (v *VRF) Name() string {
|
||||
return v.name
|
||||
}
|
19
pkg/network/water_darwin.go
Normal file
19
pkg/network/water_darwin.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/luscis/openlan/pkg/water"
|
||||
)
|
||||
|
||||
func WaterNew(c TapConfig) (*water.Interface, error) {
|
||||
deviceType := water.DeviceType(water.TAP)
|
||||
if c.Type == TUN {
|
||||
deviceType = water.TUN
|
||||
}
|
||||
cfg := water.Config{DeviceType: deviceType}
|
||||
if c.Name != "" {
|
||||
cfg.PlatformSpecificParams = water.PlatformSpecificParams{
|
||||
Name: c.Name,
|
||||
}
|
||||
}
|
||||
return water.New(cfg)
|
||||
}
|
19
pkg/network/water_linux.go
Normal file
19
pkg/network/water_linux.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/luscis/openlan/pkg/water"
|
||||
)
|
||||
|
||||
func WaterNew(c TapConfig) (*water.Interface, error) {
|
||||
deviceType := water.DeviceType(water.TAP)
|
||||
if c.Type == TUN {
|
||||
deviceType = water.TUN
|
||||
}
|
||||
cfg := water.Config{DeviceType: deviceType}
|
||||
if c.Name != "" {
|
||||
cfg.PlatformSpecificParams = water.PlatformSpecificParams{
|
||||
Name: c.Name,
|
||||
}
|
||||
}
|
||||
return water.New(cfg)
|
||||
}
|
@@ -1,21 +1,9 @@
|
||||
// +build !windows
|
||||
//go:build !linux && !darwin && !windows
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/songgao/water"
|
||||
)
|
||||
import "github.com/luscis/openlan/pkg/water"
|
||||
|
||||
func WaterNew(c TapConfig) (*water.Interface, error) {
|
||||
deviceType := water.DeviceType(water.TAP)
|
||||
if c.Type == TUN {
|
||||
deviceType = water.TUN
|
||||
}
|
||||
cfg := water.Config{DeviceType: deviceType}
|
||||
if c.Name != "" {
|
||||
cfg.PlatformSpecificParams = water.PlatformSpecificParams{
|
||||
Name: c.Name,
|
||||
}
|
||||
}
|
||||
return water.New(cfg)
|
||||
return nil, nil
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/songgao/water"
|
||||
"github.com/luscis/openlan/pkg/water"
|
||||
)
|
||||
|
||||
func WaterNew(c TapConfig) (dev *water.Interface, err error) {
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/luscis/openlan/pkg/config"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/proxy/ss"
|
||||
)
|
||||
|
||||
type Proxyer interface {
|
||||
@@ -16,20 +15,18 @@ type Proxyer interface {
|
||||
}
|
||||
|
||||
type Proxy struct {
|
||||
cfg *config.Proxy
|
||||
tcp map[string]*TcpProxy
|
||||
socks map[string]*SocksProxy
|
||||
http map[string]*HttpProxy
|
||||
shadow map[string]*ss.ShadowSocks
|
||||
cfg *config.Proxy
|
||||
tcp map[string]*TcpProxy
|
||||
socks map[string]*SocksProxy
|
||||
http map[string]*HttpProxy
|
||||
}
|
||||
|
||||
func NewProxy(cfg *config.Proxy) *Proxy {
|
||||
return &Proxy{
|
||||
cfg: cfg,
|
||||
socks: make(map[string]*SocksProxy, 32),
|
||||
tcp: make(map[string]*TcpProxy, 32),
|
||||
http: make(map[string]*HttpProxy, 32),
|
||||
shadow: make(map[string]*ss.ShadowSocks, 32),
|
||||
cfg: cfg,
|
||||
socks: make(map[string]*SocksProxy, 32),
|
||||
tcp: make(map[string]*TcpProxy, 32),
|
||||
http: make(map[string]*HttpProxy, 32),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,13 +51,6 @@ func (p *Proxy) Initialize() {
|
||||
h := NewHttpProxy(c, p)
|
||||
p.http[c.Listen] = h
|
||||
}
|
||||
for _, c := range p.cfg.Shadow {
|
||||
if c == nil || c.Server == "" {
|
||||
continue
|
||||
}
|
||||
h := ss.NewShadowSocks(c)
|
||||
p.shadow[c.Server] = h
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) Start() {
|
||||
@@ -77,9 +67,6 @@ func (p *Proxy) Start() {
|
||||
for _, h := range p.http {
|
||||
h.Start()
|
||||
}
|
||||
for _, s := range p.shadow {
|
||||
s.Start()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) Stop() {
|
||||
@@ -90,9 +77,6 @@ func (p *Proxy) Stop() {
|
||||
for _, t := range p.tcp {
|
||||
t.Stop()
|
||||
}
|
||||
for _, s := range p.shadow {
|
||||
s.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) Save() {
|
||||
|
@@ -1,9 +0,0 @@
|
||||
package ss
|
||||
|
||||
import "time"
|
||||
|
||||
var config struct {
|
||||
Verbose bool
|
||||
UDPTimeout time.Duration
|
||||
TCPCork bool
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var logger = log.New(os.Stderr, "", log.Lshortfile|log.LstdFlags)
|
||||
|
||||
func logf(f string, v ...interface{}) {
|
||||
if config.Verbose {
|
||||
_ = logger.Output(2, fmt.Sprintf(f, v...))
|
||||
}
|
||||
}
|
||||
|
||||
type logHelper struct {
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (l *logHelper) Write(p []byte) (n int, err error) {
|
||||
if config.Verbose {
|
||||
logger.Printf("%s%s\n", l.prefix, p)
|
||||
return len(p), nil
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func newLogHelper(prefix string) *logHelper {
|
||||
return &logHelper{prefix}
|
||||
}
|
@@ -1,118 +0,0 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
var pluginCmd *exec.Cmd
|
||||
|
||||
func startPlugin(plugin, pluginOpts, ssAddr string, isServer bool) (newAddr string, err error) {
|
||||
logf("starting plugin (%s) with option (%s)....", plugin, pluginOpts)
|
||||
freePort, err := getFreePort()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to fetch an unused port for plugin (%v)", err)
|
||||
}
|
||||
localHost := "127.0.0.1"
|
||||
ssHost, ssPort, err := net.SplitHostPort(ssAddr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
newAddr = localHost + ":" + freePort
|
||||
if isServer {
|
||||
if ssHost == "" {
|
||||
ssHost = "0.0.0.0"
|
||||
}
|
||||
logf("plugin (%s) will listen on %s:%s", plugin, ssHost, ssPort)
|
||||
} else {
|
||||
logf("plugin (%s) will listen on %s:%s", plugin, localHost, freePort)
|
||||
}
|
||||
err = execPlugin(plugin, pluginOpts, ssHost, ssPort, localHost, freePort)
|
||||
return
|
||||
}
|
||||
|
||||
func killPlugin() {
|
||||
if pluginCmd != nil {
|
||||
pluginCmd.Process.Signal(syscall.SIGTERM)
|
||||
waitCh := make(chan struct{})
|
||||
go func() {
|
||||
pluginCmd.Wait()
|
||||
close(waitCh)
|
||||
}()
|
||||
timeout := time.After(3 * time.Second)
|
||||
select {
|
||||
case <-waitCh:
|
||||
case <-timeout:
|
||||
pluginCmd.Process.Kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func execPlugin(plugin, pluginOpts, remoteHost, remotePort, localHost, localPort string) (err error) {
|
||||
pluginFile := plugin
|
||||
if fileExists(plugin) {
|
||||
if !filepath.IsAbs(plugin) {
|
||||
pluginFile = "./" + plugin
|
||||
}
|
||||
} else {
|
||||
pluginFile, err = exec.LookPath(plugin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
logH := newLogHelper("[" + plugin + "]: ")
|
||||
env := append(os.Environ(),
|
||||
"SS_REMOTE_HOST="+remoteHost,
|
||||
"SS_REMOTE_PORT="+remotePort,
|
||||
"SS_LOCAL_HOST="+localHost,
|
||||
"SS_LOCAL_PORT="+localPort,
|
||||
"SS_PLUGIN_OPTIONS="+pluginOpts,
|
||||
)
|
||||
cmd := &exec.Cmd{
|
||||
Path: pluginFile,
|
||||
Env: env,
|
||||
Stdout: logH,
|
||||
Stderr: logH,
|
||||
}
|
||||
if err = cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
pluginCmd = cmd
|
||||
go func() {
|
||||
if err := cmd.Wait(); err != nil {
|
||||
logf("plugin exited (%v)\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
logf("plugin exited\n")
|
||||
os.Exit(0)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileExists(filename string) bool {
|
||||
info, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
func getFreePort() (string, error) {
|
||||
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
l, err := net.ListenTCP("tcp", addr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
port := fmt.Sprintf("%d", l.Addr().(*net.TCPAddr).Port)
|
||||
l.Close()
|
||||
return port, nil
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"log"
|
||||
|
||||
c "github.com/luscis/openlan/pkg/config"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
||||
)
|
||||
|
||||
type ShadowSocks struct {
|
||||
Server string
|
||||
Key string
|
||||
Cipher string
|
||||
Password string
|
||||
Plugin string
|
||||
PluginOpts string
|
||||
Protocol string
|
||||
out *libol.SubLogger
|
||||
}
|
||||
|
||||
func NewShadowSocks(cfg *c.ShadowProxy) *ShadowSocks {
|
||||
proto := cfg.Protocol
|
||||
if proto == "" {
|
||||
proto = "tcp"
|
||||
}
|
||||
return &ShadowSocks{
|
||||
Server: cfg.Server,
|
||||
Key: cfg.Key,
|
||||
Cipher: cfg.Cipher,
|
||||
Password: cfg.Secret,
|
||||
Plugin: cfg.Plugin,
|
||||
PluginOpts: cfg.PluginOpts,
|
||||
Protocol: proto,
|
||||
out: libol.NewSubLogger(cfg.Server),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ShadowSocks) Start() {
|
||||
var key []byte
|
||||
if s.Key != "" {
|
||||
k, err := base64.URLEncoding.DecodeString(s.Key)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
key = k
|
||||
}
|
||||
addr := s.Server
|
||||
cipher := s.Cipher
|
||||
password := s.Password
|
||||
var err error
|
||||
|
||||
udpAddr := addr
|
||||
if s.Plugin != "" {
|
||||
addr, err = startPlugin(s.Plugin, s.PluginOpts, addr, true)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
ciph, err := core.PickCipher(cipher, key, password)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if s.Protocol == "udp" {
|
||||
go udpRemote(udpAddr, ciph.PacketConn)
|
||||
} else {
|
||||
go tcpRemote(addr, ciph.StreamConn)
|
||||
}
|
||||
s.out.Info("ShadowSocks.start %s:%s", s.Protocol, s.Server)
|
||||
}
|
||||
|
||||
func (s *ShadowSocks) Stop() {
|
||||
killPlugin()
|
||||
}
|
@@ -1,204 +0,0 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shadowsocks/go-shadowsocks2/socks"
|
||||
)
|
||||
|
||||
// Create a SOCKS server listening on addr and proxy to server.
|
||||
func socksLocal(addr, server string, shadow func(net.Conn) net.Conn) {
|
||||
logf("SOCKS proxy %s <-> %s", addr, server)
|
||||
tcpLocal(addr, server, shadow, func(c net.Conn) (socks.Addr, error) { return socks.Handshake(c) })
|
||||
}
|
||||
|
||||
// Create a TCP tunnel from addr to target via server.
|
||||
func tcpTun(addr, server, target string, shadow func(net.Conn) net.Conn) {
|
||||
tgt := socks.ParseAddr(target)
|
||||
if tgt == nil {
|
||||
logf("invalid target address %q", target)
|
||||
return
|
||||
}
|
||||
logf("TCP tunnel %s <-> %s <-> %s", addr, server, target)
|
||||
tcpLocal(addr, server, shadow, func(net.Conn) (socks.Addr, error) { return tgt, nil })
|
||||
}
|
||||
|
||||
// Listen on addr and proxy to server to reach target from getAddr.
|
||||
func tcpLocal(addr, server string, shadow func(net.Conn) net.Conn, getAddr func(net.Conn) (socks.Addr, error)) {
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
logf("failed to listen on %s: %v", addr, err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
logf("failed to accept: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer c.Close()
|
||||
tgt, err := getAddr(c)
|
||||
if err != nil {
|
||||
|
||||
// UDP: keep the connection until disconnect then free the UDP socket
|
||||
if err == socks.InfoUDPAssociate {
|
||||
buf := make([]byte, 1)
|
||||
// block here
|
||||
for {
|
||||
_, err := c.Read(buf)
|
||||
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||
continue
|
||||
}
|
||||
logf("UDP Associate End.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
logf("failed to get target address: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
rc, err := net.Dial("tcp", server)
|
||||
if err != nil {
|
||||
logf("failed to connect to server %v: %v", server, err)
|
||||
return
|
||||
}
|
||||
defer rc.Close()
|
||||
if config.TCPCork {
|
||||
rc = timedCork(rc, 10*time.Millisecond, 1280)
|
||||
}
|
||||
rc = shadow(rc)
|
||||
|
||||
if _, err = rc.Write(tgt); err != nil {
|
||||
logf("failed to send target address: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
logf("proxy %s <-> %s <-> %s", c.RemoteAddr(), server, tgt)
|
||||
if err = relay(rc, c); err != nil {
|
||||
logf("relay error: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// Listen on addr for incoming connections.
|
||||
func tcpRemote(addr string, shadow func(net.Conn) net.Conn) {
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
logf("failed to listen on %s: %v", addr, err)
|
||||
return
|
||||
}
|
||||
|
||||
logf("listening TCP on %s", addr)
|
||||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
logf("failed to accept: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer c.Close()
|
||||
if config.TCPCork {
|
||||
c = timedCork(c, 10*time.Millisecond, 1280)
|
||||
}
|
||||
sc := shadow(c)
|
||||
|
||||
tgt, err := socks.ReadAddr(sc)
|
||||
if err != nil {
|
||||
logf("failed to get target address from %v: %v", c.RemoteAddr(), err)
|
||||
// drain c to avoid leaking server behavioral features
|
||||
// see https://www.ndss-symposium.org/ndss-paper/detecting-probe-resistant-proxies/
|
||||
_, err = io.Copy(io.Discard, c)
|
||||
if err != nil {
|
||||
logf("discard error: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
rc, err := net.Dial("tcp", tgt.String())
|
||||
if err != nil {
|
||||
logf("failed to connect to target: %v", err)
|
||||
return
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
logf("proxy %s <-> %s", c.RemoteAddr(), tgt)
|
||||
if err = relay(sc, rc); err != nil {
|
||||
logf("relay error: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// relay copies between left and right bidirectionally
|
||||
func relay(left, right net.Conn) error {
|
||||
var err, err1 error
|
||||
var wg sync.WaitGroup
|
||||
var wait = 5 * time.Second
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_, err1 = io.Copy(right, left)
|
||||
right.SetReadDeadline(time.Now().Add(wait)) // unblock read on right
|
||||
}()
|
||||
_, err = io.Copy(left, right)
|
||||
left.SetReadDeadline(time.Now().Add(wait)) // unblock read on left
|
||||
wg.Wait()
|
||||
if err1 != nil && !errors.Is(err1, os.ErrDeadlineExceeded) { // requires Go 1.15+
|
||||
return err1
|
||||
}
|
||||
if err != nil && !errors.Is(err, os.ErrDeadlineExceeded) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type corkedConn struct {
|
||||
net.Conn
|
||||
bufw *bufio.Writer
|
||||
corked bool
|
||||
delay time.Duration
|
||||
err error
|
||||
lock sync.Mutex
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
func timedCork(c net.Conn, d time.Duration, bufSize int) net.Conn {
|
||||
return &corkedConn{
|
||||
Conn: c,
|
||||
bufw: bufio.NewWriterSize(c, bufSize),
|
||||
corked: true,
|
||||
delay: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *corkedConn) Write(p []byte) (int, error) {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
if w.corked {
|
||||
w.once.Do(func() {
|
||||
time.AfterFunc(w.delay, func() {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
w.corked = false
|
||||
w.err = w.bufw.Flush()
|
||||
})
|
||||
})
|
||||
return w.bufw.Write(p)
|
||||
}
|
||||
return w.Conn.Write(p)
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/shadowsocks/go-shadowsocks2/pfutil"
|
||||
"github.com/shadowsocks/go-shadowsocks2/socks"
|
||||
)
|
||||
|
||||
func redirLocal(addr, server string, shadow func(net.Conn) net.Conn) {
|
||||
tcpLocal(addr, server, shadow, natLookup)
|
||||
}
|
||||
|
||||
func redir6Local(addr, server string, shadow func(net.Conn) net.Conn) {
|
||||
panic("TCP6 redirect not supported")
|
||||
}
|
||||
|
||||
func natLookup(c net.Conn) (socks.Addr, error) {
|
||||
if tc, ok := c.(*net.TCPConn); ok {
|
||||
addr, err := pfutil.NatLookup(tc)
|
||||
return socks.ParseAddr(addr.String()), err
|
||||
}
|
||||
panic("not TCP connection")
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/shadowsocks/go-shadowsocks2/nfutil"
|
||||
"github.com/shadowsocks/go-shadowsocks2/socks"
|
||||
)
|
||||
|
||||
func getOrigDst(c net.Conn, ipv6 bool) (socks.Addr, error) {
|
||||
if tc, ok := c.(*net.TCPConn); ok {
|
||||
addr, err := nfutil.GetOrigDst(tc, ipv6)
|
||||
return socks.ParseAddr(addr.String()), err
|
||||
}
|
||||
panic("not a TCP connection")
|
||||
}
|
||||
|
||||
// Listen on addr for netfilter redirected TCP connections
|
||||
func redirLocal(addr, server string, shadow func(net.Conn) net.Conn) {
|
||||
logf("TCP redirect %s <-> %s", addr, server)
|
||||
tcpLocal(addr, server, shadow, func(c net.Conn) (socks.Addr, error) { return getOrigDst(c, false) })
|
||||
}
|
||||
|
||||
// Listen on addr for netfilter redirected TCP IPv6 connections.
|
||||
func redir6Local(addr, server string, shadow func(net.Conn) net.Conn) {
|
||||
logf("TCP6 redirect %s <-> %s", addr, server)
|
||||
tcpLocal(addr, server, shadow, func(c net.Conn) (socks.Addr, error) { return getOrigDst(c, true) })
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
// +build !linux,!darwin
|
||||
|
||||
package ss
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func redirLocal(addr, server string, shadow func(net.Conn) net.Conn) {
|
||||
logf("TCP redirect not supported")
|
||||
}
|
||||
|
||||
func redir6Local(addr, server string, shadow func(net.Conn) net.Conn) {
|
||||
logf("TCP6 redirect not supported")
|
||||
}
|
@@ -1,253 +0,0 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shadowsocks/go-shadowsocks2/socks"
|
||||
)
|
||||
|
||||
type mode int
|
||||
|
||||
const (
|
||||
remoteServer mode = iota
|
||||
relayClient
|
||||
socksClient
|
||||
)
|
||||
|
||||
const udpBufSize = 64 * 1024
|
||||
|
||||
// Listen on laddr for UDP packets, encrypt and send to server to reach target.
|
||||
func udpLocal(laddr, server, target string, shadow func(net.PacketConn) net.PacketConn) {
|
||||
srvAddr, err := net.ResolveUDPAddr("udp", server)
|
||||
if err != nil {
|
||||
logf("UDP server address error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tgt := socks.ParseAddr(target)
|
||||
if tgt == nil {
|
||||
err = fmt.Errorf("invalid target address: %q", target)
|
||||
logf("UDP target address error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("udp", laddr)
|
||||
if err != nil {
|
||||
logf("UDP local listen error: %v", err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
nm := newNATmap(config.UDPTimeout)
|
||||
buf := make([]byte, udpBufSize)
|
||||
copy(buf, tgt)
|
||||
|
||||
logf("UDP tunnel %s <-> %s <-> %s", laddr, server, target)
|
||||
for {
|
||||
n, raddr, err := c.ReadFrom(buf[len(tgt):])
|
||||
if err != nil {
|
||||
logf("UDP local read error: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
pc := nm.Get(raddr.String())
|
||||
if pc == nil {
|
||||
pc, err = net.ListenPacket("udp", "")
|
||||
if err != nil {
|
||||
logf("UDP local listen error: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
pc = shadow(pc)
|
||||
nm.Add(raddr, c, pc, relayClient)
|
||||
}
|
||||
|
||||
_, err = pc.WriteTo(buf[:len(tgt)+n], srvAddr)
|
||||
if err != nil {
|
||||
logf("UDP local write error: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Listen on laddr for Socks5 UDP packets, encrypt and send to server to reach target.
|
||||
func udpSocksLocal(laddr, server string, shadow func(net.PacketConn) net.PacketConn) {
|
||||
srvAddr, err := net.ResolveUDPAddr("udp", server)
|
||||
if err != nil {
|
||||
logf("UDP server address error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("udp", laddr)
|
||||
if err != nil {
|
||||
logf("UDP local listen error: %v", err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
nm := newNATmap(config.UDPTimeout)
|
||||
buf := make([]byte, udpBufSize)
|
||||
|
||||
for {
|
||||
n, raddr, err := c.ReadFrom(buf)
|
||||
if err != nil {
|
||||
logf("UDP local read error: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
pc := nm.Get(raddr.String())
|
||||
if pc == nil {
|
||||
pc, err = net.ListenPacket("udp", "")
|
||||
if err != nil {
|
||||
logf("UDP local listen error: %v", err)
|
||||
continue
|
||||
}
|
||||
logf("UDP socks tunnel %s <-> %s <-> %s", laddr, server, socks.Addr(buf[3:]))
|
||||
pc = shadow(pc)
|
||||
nm.Add(raddr, c, pc, socksClient)
|
||||
}
|
||||
|
||||
_, err = pc.WriteTo(buf[3:n], srvAddr)
|
||||
if err != nil {
|
||||
logf("UDP local write error: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Listen on addr for encrypted packets and basically do UDP NAT.
|
||||
func udpRemote(addr string, shadow func(net.PacketConn) net.PacketConn) {
|
||||
c, err := net.ListenPacket("udp", addr)
|
||||
if err != nil {
|
||||
logf("UDP remote listen error: %v", err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
c = shadow(c)
|
||||
|
||||
nm := newNATmap(config.UDPTimeout)
|
||||
buf := make([]byte, udpBufSize)
|
||||
|
||||
logf("listening UDP on %s", addr)
|
||||
for {
|
||||
n, raddr, err := c.ReadFrom(buf)
|
||||
if err != nil {
|
||||
logf("UDP remote read error: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
tgtAddr := socks.SplitAddr(buf[:n])
|
||||
if tgtAddr == nil {
|
||||
logf("failed to split target address from packet: %q", buf[:n])
|
||||
continue
|
||||
}
|
||||
|
||||
tgtUDPAddr, err := net.ResolveUDPAddr("udp", tgtAddr.String())
|
||||
if err != nil {
|
||||
logf("failed to resolve target UDP address: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
payload := buf[len(tgtAddr):n]
|
||||
|
||||
pc := nm.Get(raddr.String())
|
||||
if pc == nil {
|
||||
pc, err = net.ListenPacket("udp", "")
|
||||
if err != nil {
|
||||
logf("UDP remote listen error: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
nm.Add(raddr, c, pc, remoteServer)
|
||||
}
|
||||
|
||||
_, err = pc.WriteTo(payload, tgtUDPAddr) // accept only UDPAddr despite the signature
|
||||
if err != nil {
|
||||
logf("UDP remote write error: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Packet NAT table
|
||||
type natmap struct {
|
||||
sync.RWMutex
|
||||
m map[string]net.PacketConn
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func newNATmap(timeout time.Duration) *natmap {
|
||||
m := &natmap{}
|
||||
m.m = make(map[string]net.PacketConn)
|
||||
m.timeout = timeout
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *natmap) Get(key string) net.PacketConn {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
return m.m[key]
|
||||
}
|
||||
|
||||
func (m *natmap) Set(key string, pc net.PacketConn) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.m[key] = pc
|
||||
}
|
||||
|
||||
func (m *natmap) Del(key string) net.PacketConn {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
pc, ok := m.m[key]
|
||||
if ok {
|
||||
delete(m.m, key)
|
||||
return pc
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *natmap) Add(peer net.Addr, dst, src net.PacketConn, role mode) {
|
||||
m.Set(peer.String(), src)
|
||||
|
||||
go func() {
|
||||
timedCopy(dst, peer, src, m.timeout, role)
|
||||
if pc := m.Del(peer.String()); pc != nil {
|
||||
pc.Close()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// copy from src to dst at target with read timeout
|
||||
func timedCopy(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration, role mode) error {
|
||||
buf := make([]byte, udpBufSize)
|
||||
|
||||
for {
|
||||
src.SetReadDeadline(time.Now().Add(timeout))
|
||||
n, raddr, err := src.ReadFrom(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch role {
|
||||
case remoteServer: // server -> client: add original packet source
|
||||
srcAddr := socks.ParseAddr(raddr.String())
|
||||
copy(buf[len(srcAddr):], buf[:n])
|
||||
copy(buf, srcAddr)
|
||||
_, err = dst.WriteTo(buf[:len(srcAddr)+n], target)
|
||||
case relayClient: // client -> user: strip original packet source
|
||||
srcAddr := socks.SplitAddr(buf[:n])
|
||||
_, err = dst.WriteTo(buf[len(srcAddr):n], target)
|
||||
case socksClient: // client -> socks5 program: just set RSV and FRAG = 0
|
||||
_, err = dst.WriteTo(append([]byte{0, 0, 0}, buf[:n]...), target)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
// +build !linux,!darwin,!windows
|
||||
//go:build !linux && !darwin && !windows
|
||||
|
||||
package water
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// +build linux,go1.11
|
||||
//go:build linux && go1.11
|
||||
|
||||
package water
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// +build !linux,!darwin,!windows
|
||||
//go:build !linux && !darwin && !windows
|
||||
|
||||
package water
|
||||
|
25
vendor/github.com/cenkalti/backoff/v4/.gitignore
generated
vendored
25
vendor/github.com/cenkalti/backoff/v4/.gitignore
generated
vendored
@@ -1,25 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
|
||||
# IDEs
|
||||
.idea/
|
10
vendor/github.com/cenkalti/backoff/v4/.travis.yml
generated
vendored
10
vendor/github.com/cenkalti/backoff/v4/.travis.yml
generated
vendored
@@ -1,10 +0,0 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.13
|
||||
- 1.x
|
||||
- tip
|
||||
before_install:
|
||||
- go get github.com/mattn/goveralls
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
script:
|
||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
20
vendor/github.com/cenkalti/backoff/v4/LICENSE
generated
vendored
20
vendor/github.com/cenkalti/backoff/v4/LICENSE
generated
vendored
@@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Cenk Altı
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
32
vendor/github.com/cenkalti/backoff/v4/README.md
generated
vendored
32
vendor/github.com/cenkalti/backoff/v4/README.md
generated
vendored
@@ -1,32 +0,0 @@
|
||||
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
|
||||
|
||||
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
|
||||
|
||||
[Exponential backoff][exponential backoff wiki]
|
||||
is an algorithm that uses feedback to multiplicatively decrease the rate of some process,
|
||||
in order to gradually find an acceptable rate.
|
||||
The retries exponentially increase and stop increasing when a certain threshold is met.
|
||||
|
||||
## Usage
|
||||
|
||||
Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end.
|
||||
|
||||
Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation.
|
||||
|
||||
## Contributing
|
||||
|
||||
* I would like to keep this library as small as possible.
|
||||
* Please don't send a PR without opening an issue and discussing it first.
|
||||
* If proposed change is not a common use case, I will probably not accept it.
|
||||
|
||||
[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4
|
||||
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
|
||||
[travis]: https://travis-ci.org/cenkalti/backoff
|
||||
[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master
|
||||
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
|
||||
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
|
||||
|
||||
[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java
|
||||
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
|
||||
|
||||
[advanced example]: https://pkg.go.dev/github.com/cenkalti/backoff/v4?tab=doc#pkg-examples
|
66
vendor/github.com/cenkalti/backoff/v4/backoff.go
generated
vendored
66
vendor/github.com/cenkalti/backoff/v4/backoff.go
generated
vendored
@@ -1,66 +0,0 @@
|
||||
// Package backoff implements backoff algorithms for retrying operations.
|
||||
//
|
||||
// Use Retry function for retrying operations that may fail.
|
||||
// If Retry does not meet your needs,
|
||||
// copy/paste the function into your project and modify as you wish.
|
||||
//
|
||||
// There is also Ticker type similar to time.Ticker.
|
||||
// You can use it if you need to work with channels.
|
||||
//
|
||||
// See Examples section below for usage examples.
|
||||
package backoff
|
||||
|
||||
import "time"
|
||||
|
||||
// BackOff is a backoff policy for retrying an operation.
|
||||
type BackOff interface {
|
||||
// NextBackOff returns the duration to wait before retrying the operation,
|
||||
// or backoff. Stop to indicate that no more retries should be made.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// duration := backoff.NextBackOff();
|
||||
// if (duration == backoff.Stop) {
|
||||
// // Do not retry operation.
|
||||
// } else {
|
||||
// // Sleep for duration and retry operation.
|
||||
// }
|
||||
//
|
||||
NextBackOff() time.Duration
|
||||
|
||||
// Reset to initial state.
|
||||
Reset()
|
||||
}
|
||||
|
||||
// Stop indicates that no more retries should be made for use in NextBackOff().
|
||||
const Stop time.Duration = -1
|
||||
|
||||
// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
|
||||
// meaning that the operation is retried immediately without waiting, indefinitely.
|
||||
type ZeroBackOff struct{}
|
||||
|
||||
func (b *ZeroBackOff) Reset() {}
|
||||
|
||||
func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
|
||||
|
||||
// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
|
||||
// NextBackOff(), meaning that the operation should never be retried.
|
||||
type StopBackOff struct{}
|
||||
|
||||
func (b *StopBackOff) Reset() {}
|
||||
|
||||
func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
|
||||
|
||||
// ConstantBackOff is a backoff policy that always returns the same backoff delay.
|
||||
// This is in contrast to an exponential backoff policy,
|
||||
// which returns a delay that grows longer as you call NextBackOff() over and over again.
|
||||
type ConstantBackOff struct {
|
||||
Interval time.Duration
|
||||
}
|
||||
|
||||
func (b *ConstantBackOff) Reset() {}
|
||||
func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval }
|
||||
|
||||
func NewConstantBackOff(d time.Duration) *ConstantBackOff {
|
||||
return &ConstantBackOff{Interval: d}
|
||||
}
|
62
vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
62
vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
@@ -1,62 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BackOffContext is a backoff policy that stops retrying after the context
|
||||
// is canceled.
|
||||
type BackOffContext interface { // nolint: golint
|
||||
BackOff
|
||||
Context() context.Context
|
||||
}
|
||||
|
||||
type backOffContext struct {
|
||||
BackOff
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// WithContext returns a BackOffContext with context ctx
|
||||
//
|
||||
// ctx must not be nil
|
||||
func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint
|
||||
if ctx == nil {
|
||||
panic("nil context")
|
||||
}
|
||||
|
||||
if b, ok := b.(*backOffContext); ok {
|
||||
return &backOffContext{
|
||||
BackOff: b.BackOff,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
return &backOffContext{
|
||||
BackOff: b,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
func getContext(b BackOff) context.Context {
|
||||
if cb, ok := b.(BackOffContext); ok {
|
||||
return cb.Context()
|
||||
}
|
||||
if tb, ok := b.(*backOffTries); ok {
|
||||
return getContext(tb.delegate)
|
||||
}
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
func (b *backOffContext) Context() context.Context {
|
||||
return b.ctx
|
||||
}
|
||||
|
||||
func (b *backOffContext) NextBackOff() time.Duration {
|
||||
select {
|
||||
case <-b.ctx.Done():
|
||||
return Stop
|
||||
default:
|
||||
return b.BackOff.NextBackOff()
|
||||
}
|
||||
}
|
158
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
158
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
@@ -1,158 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
ExponentialBackOff is a backoff implementation that increases the backoff
|
||||
period for each retry attempt using a randomization function that grows exponentially.
|
||||
|
||||
NextBackOff() is calculated using the following formula:
|
||||
|
||||
randomized interval =
|
||||
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
|
||||
|
||||
In other words NextBackOff() will range between the randomization factor
|
||||
percentage below and above the retry interval.
|
||||
|
||||
For example, given the following parameters:
|
||||
|
||||
RetryInterval = 2
|
||||
RandomizationFactor = 0.5
|
||||
Multiplier = 2
|
||||
|
||||
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
|
||||
multiplied by the exponential, that is, between 2 and 6 seconds.
|
||||
|
||||
Note: MaxInterval caps the RetryInterval and not the randomized interval.
|
||||
|
||||
If the time elapsed since an ExponentialBackOff instance is created goes past the
|
||||
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
|
||||
|
||||
The elapsed time can be reset by calling Reset().
|
||||
|
||||
Example: Given the following default arguments, for 10 tries the sequence will be,
|
||||
and assuming we go over the MaxElapsedTime on the 10th try:
|
||||
|
||||
Request # RetryInterval (seconds) Randomized Interval (seconds)
|
||||
|
||||
1 0.5 [0.25, 0.75]
|
||||
2 0.75 [0.375, 1.125]
|
||||
3 1.125 [0.562, 1.687]
|
||||
4 1.687 [0.8435, 2.53]
|
||||
5 2.53 [1.265, 3.795]
|
||||
6 3.795 [1.897, 5.692]
|
||||
7 5.692 [2.846, 8.538]
|
||||
8 8.538 [4.269, 12.807]
|
||||
9 12.807 [6.403, 19.210]
|
||||
10 19.210 backoff.Stop
|
||||
|
||||
Note: Implementation is not thread-safe.
|
||||
*/
|
||||
type ExponentialBackOff struct {
|
||||
InitialInterval time.Duration
|
||||
RandomizationFactor float64
|
||||
Multiplier float64
|
||||
MaxInterval time.Duration
|
||||
// After MaxElapsedTime the ExponentialBackOff returns Stop.
|
||||
// It never stops if MaxElapsedTime == 0.
|
||||
MaxElapsedTime time.Duration
|
||||
Stop time.Duration
|
||||
Clock Clock
|
||||
|
||||
currentInterval time.Duration
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
// Clock is an interface that returns current time for BackOff.
|
||||
type Clock interface {
|
||||
Now() time.Time
|
||||
}
|
||||
|
||||
// Default values for ExponentialBackOff.
|
||||
const (
|
||||
DefaultInitialInterval = 500 * time.Millisecond
|
||||
DefaultRandomizationFactor = 0.5
|
||||
DefaultMultiplier = 1.5
|
||||
DefaultMaxInterval = 60 * time.Second
|
||||
DefaultMaxElapsedTime = 15 * time.Minute
|
||||
)
|
||||
|
||||
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
|
||||
func NewExponentialBackOff() *ExponentialBackOff {
|
||||
b := &ExponentialBackOff{
|
||||
InitialInterval: DefaultInitialInterval,
|
||||
RandomizationFactor: DefaultRandomizationFactor,
|
||||
Multiplier: DefaultMultiplier,
|
||||
MaxInterval: DefaultMaxInterval,
|
||||
MaxElapsedTime: DefaultMaxElapsedTime,
|
||||
Stop: Stop,
|
||||
Clock: SystemClock,
|
||||
}
|
||||
b.Reset()
|
||||
return b
|
||||
}
|
||||
|
||||
type systemClock struct{}
|
||||
|
||||
func (t systemClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// SystemClock implements Clock interface that uses time.Now().
|
||||
var SystemClock = systemClock{}
|
||||
|
||||
// Reset the interval back to the initial retry interval and restarts the timer.
|
||||
// Reset must be called before using b.
|
||||
func (b *ExponentialBackOff) Reset() {
|
||||
b.currentInterval = b.InitialInterval
|
||||
b.startTime = b.Clock.Now()
|
||||
}
|
||||
|
||||
// NextBackOff calculates the next backoff interval using the formula:
|
||||
// Randomized interval = RetryInterval * (1 ± RandomizationFactor)
|
||||
func (b *ExponentialBackOff) NextBackOff() time.Duration {
|
||||
// Make sure we have not gone over the maximum elapsed time.
|
||||
elapsed := b.GetElapsedTime()
|
||||
next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
|
||||
b.incrementCurrentInterval()
|
||||
if b.MaxElapsedTime != 0 && elapsed+next > b.MaxElapsedTime {
|
||||
return b.Stop
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
||||
// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
|
||||
// is created and is reset when Reset() is called.
|
||||
//
|
||||
// The elapsed time is computed using time.Now().UnixNano(). It is
|
||||
// safe to call even while the backoff policy is used by a running
|
||||
// ticker.
|
||||
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
|
||||
return b.Clock.Now().Sub(b.startTime)
|
||||
}
|
||||
|
||||
// Increments the current interval by multiplying it with the multiplier.
|
||||
func (b *ExponentialBackOff) incrementCurrentInterval() {
|
||||
// Check for overflow, if overflow is detected set the current interval to the max interval.
|
||||
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
|
||||
b.currentInterval = b.MaxInterval
|
||||
} else {
|
||||
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a random value from the following interval:
|
||||
// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval].
|
||||
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
||||
var delta = randomizationFactor * float64(currentInterval)
|
||||
var minInterval = float64(currentInterval) - delta
|
||||
var maxInterval = float64(currentInterval) + delta
|
||||
|
||||
// Get a random value from the range [minInterval, maxInterval].
|
||||
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
|
||||
// we want a 33% chance for selecting either 1, 2 or 3.
|
||||
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
|
||||
}
|
112
vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
112
vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
@@ -1,112 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// An Operation is executing by Retry() or RetryNotify().
|
||||
// The operation will be retried using a backoff policy if it returns an error.
|
||||
type Operation func() error
|
||||
|
||||
// Notify is a notify-on-error function. It receives an operation error and
|
||||
// backoff delay if the operation failed (with an error).
|
||||
//
|
||||
// NOTE that if the backoff policy stated to stop retrying,
|
||||
// the notify function isn't called.
|
||||
type Notify func(error, time.Duration)
|
||||
|
||||
// Retry the operation o until it does not return error or BackOff stops.
|
||||
// o is guaranteed to be run at least once.
|
||||
//
|
||||
// If o returns a *PermanentError, the operation is not retried, and the
|
||||
// wrapped error is returned.
|
||||
//
|
||||
// Retry sleeps the goroutine for the duration returned by BackOff after a
|
||||
// failed operation returns.
|
||||
func Retry(o Operation, b BackOff) error {
|
||||
return RetryNotify(o, b, nil)
|
||||
}
|
||||
|
||||
// RetryNotify calls notify function with the error and wait duration
|
||||
// for each failed attempt before sleep.
|
||||
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
|
||||
return RetryNotifyWithTimer(operation, b, notify, nil)
|
||||
}
|
||||
|
||||
// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer
|
||||
// for each failed attempt before sleep.
|
||||
// A default timer that uses system timer is used when nil is passed.
|
||||
func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error {
|
||||
var err error
|
||||
var next time.Duration
|
||||
if t == nil {
|
||||
t = &defaultTimer{}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
t.Stop()
|
||||
}()
|
||||
|
||||
ctx := getContext(b)
|
||||
|
||||
b.Reset()
|
||||
for {
|
||||
if err = operation(); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var permanent *PermanentError
|
||||
if errors.As(err, &permanent) {
|
||||
return permanent.Err
|
||||
}
|
||||
|
||||
if next = b.NextBackOff(); next == Stop {
|
||||
if cerr := ctx.Err(); cerr != nil {
|
||||
return cerr
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if notify != nil {
|
||||
notify(err, next)
|
||||
}
|
||||
|
||||
t.Start(next)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-t.C():
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PermanentError signals that the operation should not be retried.
|
||||
type PermanentError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *PermanentError) Error() string {
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
func (e *PermanentError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
func (e *PermanentError) Is(target error) bool {
|
||||
_, ok := target.(*PermanentError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Permanent wraps the given err in a *PermanentError.
|
||||
func Permanent(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &PermanentError{
|
||||
Err: err,
|
||||
}
|
||||
}
|
97
vendor/github.com/cenkalti/backoff/v4/ticker.go
generated
vendored
97
vendor/github.com/cenkalti/backoff/v4/ticker.go
generated
vendored
@@ -1,97 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
|
||||
//
|
||||
// Ticks will continue to arrive when the previous operation is still running,
|
||||
// so operations that take a while to fail could run in quick succession.
|
||||
type Ticker struct {
|
||||
C <-chan time.Time
|
||||
c chan time.Time
|
||||
b BackOff
|
||||
ctx context.Context
|
||||
timer Timer
|
||||
stop chan struct{}
|
||||
stopOnce sync.Once
|
||||
}
|
||||
|
||||
// NewTicker returns a new Ticker containing a channel that will send
|
||||
// the time at times specified by the BackOff argument. Ticker is
|
||||
// guaranteed to tick at least once. The channel is closed when Stop
|
||||
// method is called or BackOff stops. It is not safe to manipulate the
|
||||
// provided backoff policy (notably calling NextBackOff or Reset)
|
||||
// while the ticker is running.
|
||||
func NewTicker(b BackOff) *Ticker {
|
||||
return NewTickerWithTimer(b, &defaultTimer{})
|
||||
}
|
||||
|
||||
// NewTickerWithTimer returns a new Ticker with a custom timer.
|
||||
// A default timer that uses system timer is used when nil is passed.
|
||||
func NewTickerWithTimer(b BackOff, timer Timer) *Ticker {
|
||||
if timer == nil {
|
||||
timer = &defaultTimer{}
|
||||
}
|
||||
c := make(chan time.Time)
|
||||
t := &Ticker{
|
||||
C: c,
|
||||
c: c,
|
||||
b: b,
|
||||
ctx: getContext(b),
|
||||
timer: timer,
|
||||
stop: make(chan struct{}),
|
||||
}
|
||||
t.b.Reset()
|
||||
go t.run()
|
||||
return t
|
||||
}
|
||||
|
||||
// Stop turns off a ticker. After Stop, no more ticks will be sent.
|
||||
func (t *Ticker) Stop() {
|
||||
t.stopOnce.Do(func() { close(t.stop) })
|
||||
}
|
||||
|
||||
func (t *Ticker) run() {
|
||||
c := t.c
|
||||
defer close(c)
|
||||
|
||||
// Ticker is guaranteed to tick at least once.
|
||||
afterC := t.send(time.Now())
|
||||
|
||||
for {
|
||||
if afterC == nil {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case tick := <-afterC:
|
||||
afterC = t.send(tick)
|
||||
case <-t.stop:
|
||||
t.c = nil // Prevent future ticks from being sent to the channel.
|
||||
return
|
||||
case <-t.ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Ticker) send(tick time.Time) <-chan time.Time {
|
||||
select {
|
||||
case t.c <- tick:
|
||||
case <-t.stop:
|
||||
return nil
|
||||
}
|
||||
|
||||
next := t.b.NextBackOff()
|
||||
if next == Stop {
|
||||
t.Stop()
|
||||
return nil
|
||||
}
|
||||
|
||||
t.timer.Start(next)
|
||||
return t.timer.C()
|
||||
}
|
35
vendor/github.com/cenkalti/backoff/v4/timer.go
generated
vendored
35
vendor/github.com/cenkalti/backoff/v4/timer.go
generated
vendored
@@ -1,35 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import "time"
|
||||
|
||||
type Timer interface {
|
||||
Start(duration time.Duration)
|
||||
Stop()
|
||||
C() <-chan time.Time
|
||||
}
|
||||
|
||||
// defaultTimer implements Timer interface using time.Timer
|
||||
type defaultTimer struct {
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
// C returns the timers channel which receives the current time when the timer fires.
|
||||
func (t *defaultTimer) C() <-chan time.Time {
|
||||
return t.timer.C
|
||||
}
|
||||
|
||||
// Start starts the timer to fire after the given duration
|
||||
func (t *defaultTimer) Start(duration time.Duration) {
|
||||
if t.timer == nil {
|
||||
t.timer = time.NewTimer(duration)
|
||||
} else {
|
||||
t.timer.Reset(duration)
|
||||
}
|
||||
}
|
||||
|
||||
// Stop is called when the timer is not used anymore and resources may be freed.
|
||||
func (t *defaultTimer) Stop() {
|
||||
if t.timer != nil {
|
||||
t.timer.Stop()
|
||||
}
|
||||
}
|
38
vendor/github.com/cenkalti/backoff/v4/tries.go
generated
vendored
38
vendor/github.com/cenkalti/backoff/v4/tries.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import "time"
|
||||
|
||||
/*
|
||||
WithMaxRetries creates a wrapper around another BackOff, which will
|
||||
return Stop if NextBackOff() has been called too many times since
|
||||
the last time Reset() was called
|
||||
|
||||
Note: Implementation is not thread-safe.
|
||||
*/
|
||||
func WithMaxRetries(b BackOff, max uint64) BackOff {
|
||||
return &backOffTries{delegate: b, maxTries: max}
|
||||
}
|
||||
|
||||
type backOffTries struct {
|
||||
delegate BackOff
|
||||
maxTries uint64
|
||||
numTries uint64
|
||||
}
|
||||
|
||||
func (b *backOffTries) NextBackOff() time.Duration {
|
||||
if b.maxTries == 0 {
|
||||
return Stop
|
||||
}
|
||||
if b.maxTries > 0 {
|
||||
if b.maxTries <= b.numTries {
|
||||
return Stop
|
||||
}
|
||||
b.numTries++
|
||||
}
|
||||
return b.delegate.NextBackOff()
|
||||
}
|
||||
|
||||
func (b *backOffTries) Reset() {
|
||||
b.numTries = 0
|
||||
b.delegate.Reset()
|
||||
}
|
22
vendor/github.com/cenkalti/hub/.gitignore
generated
vendored
22
vendor/github.com/cenkalti/hub/.gitignore
generated
vendored
@@ -1,22 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
3
vendor/github.com/cenkalti/hub/.travis.yml
generated
vendored
3
vendor/github.com/cenkalti/hub/.travis.yml
generated
vendored
@@ -1,3 +0,0 @@
|
||||
language: go
|
||||
go: 1.2
|
||||
|
20
vendor/github.com/cenkalti/hub/LICENSE
generated
vendored
20
vendor/github.com/cenkalti/hub/LICENSE
generated
vendored
@@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Cenk Altı
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
5
vendor/github.com/cenkalti/hub/README.md
generated
vendored
5
vendor/github.com/cenkalti/hub/README.md
generated
vendored
@@ -1,5 +0,0 @@
|
||||
hub
|
||||
===
|
||||
|
||||
[](https://godoc.org/github.com/cenkalti/hub)
|
||||
[](https://travis-ci.org/cenkalti/hub)
|
82
vendor/github.com/cenkalti/hub/hub.go
generated
vendored
82
vendor/github.com/cenkalti/hub/hub.go
generated
vendored
@@ -1,82 +0,0 @@
|
||||
// Package hub provides a simple event dispatcher for publish/subscribe pattern.
|
||||
package hub
|
||||
|
||||
import "sync"
|
||||
|
||||
type Kind int
|
||||
|
||||
// Event is an interface for published events.
|
||||
type Event interface {
|
||||
Kind() Kind
|
||||
}
|
||||
|
||||
// Hub is an event dispatcher, publishes events to the subscribers
|
||||
// which are subscribed for a specific event type.
|
||||
// Optimized for publish calls.
|
||||
// The handlers may be called in order different than they are registered.
|
||||
type Hub struct {
|
||||
subscribers map[Kind][]handler
|
||||
m sync.RWMutex
|
||||
seq uint64
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
f func(Event)
|
||||
id uint64
|
||||
}
|
||||
|
||||
// Subscribe registers f for the event of a specific kind.
|
||||
func (h *Hub) Subscribe(kind Kind, f func(Event)) (cancel func()) {
|
||||
var cancelled bool
|
||||
h.m.Lock()
|
||||
h.seq++
|
||||
id := h.seq
|
||||
if h.subscribers == nil {
|
||||
h.subscribers = make(map[Kind][]handler)
|
||||
}
|
||||
h.subscribers[kind] = append(h.subscribers[kind], handler{id: id, f: f})
|
||||
h.m.Unlock()
|
||||
return func() {
|
||||
h.m.Lock()
|
||||
if cancelled {
|
||||
h.m.Unlock()
|
||||
return
|
||||
}
|
||||
cancelled = true
|
||||
a := h.subscribers[kind]
|
||||
for i, f := range a {
|
||||
if f.id == id {
|
||||
a[i], h.subscribers[kind] = a[len(a)-1], a[:len(a)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(a) == 0 {
|
||||
delete(h.subscribers, kind)
|
||||
}
|
||||
h.m.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// Publish an event to the subscribers.
|
||||
func (h *Hub) Publish(e Event) {
|
||||
h.m.RLock()
|
||||
if handlers, ok := h.subscribers[e.Kind()]; ok {
|
||||
for _, h := range handlers {
|
||||
h.f(e)
|
||||
}
|
||||
}
|
||||
h.m.RUnlock()
|
||||
}
|
||||
|
||||
// DefaultHub is the default Hub used by Publish and Subscribe.
|
||||
var DefaultHub Hub
|
||||
|
||||
// Subscribe registers f for the event of a specific kind in the DefaultHub.
|
||||
func Subscribe(kind Kind, f func(Event)) (cancel func()) {
|
||||
return DefaultHub.Subscribe(kind, f)
|
||||
}
|
||||
|
||||
// Publish an event to the subscribers in DefaultHub.
|
||||
func Publish(e Event) {
|
||||
DefaultHub.Publish(e)
|
||||
}
|
23
vendor/github.com/cenkalti/rpc2/.gitignore
generated
vendored
23
vendor/github.com/cenkalti/rpc2/.gitignore
generated
vendored
@@ -1,23 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
9
vendor/github.com/cenkalti/rpc2/.travis.yml
generated
vendored
9
vendor/github.com/cenkalti/rpc2/.travis.yml
generated
vendored
@@ -1,9 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.15
|
||||
- tip
|
||||
|
||||
arch:
|
||||
- amd64
|
||||
- ppc64le
|
21
vendor/github.com/cenkalti/rpc2/LICENSE
generated
vendored
21
vendor/github.com/cenkalti/rpc2/LICENSE
generated
vendored
@@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Cenk Altı
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
82
vendor/github.com/cenkalti/rpc2/README.md
generated
vendored
82
vendor/github.com/cenkalti/rpc2/README.md
generated
vendored
@@ -1,82 +0,0 @@
|
||||
rpc2
|
||||
====
|
||||
|
||||
[](https://godoc.org/github.com/cenkalti/rpc2)
|
||||
[](https://travis-ci.org/cenkalti/rpc2)
|
||||
|
||||
rpc2 is a fork of net/rpc package in the standard library.
|
||||
The main goal is to add bi-directional support to calls.
|
||||
That means server can call the methods of client.
|
||||
This is not possible with net/rpc package.
|
||||
In order to do this it adds a `*Client` argument to method signatures.
|
||||
|
||||
Install
|
||||
--------
|
||||
|
||||
go get github.com/cenkalti/rpc2
|
||||
|
||||
Example server
|
||||
---------------
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/cenkalti/rpc2"
|
||||
)
|
||||
|
||||
type Args struct{ A, B int }
|
||||
type Reply int
|
||||
|
||||
func main() {
|
||||
srv := rpc2.NewServer()
|
||||
srv.Handle("add", func(client *rpc2.Client, args *Args, reply *Reply) error {
|
||||
|
||||
// Reversed call (server to client)
|
||||
var rep Reply
|
||||
client.Call("mult", Args{2, 3}, &rep)
|
||||
fmt.Println("mult result:", rep)
|
||||
|
||||
*reply = Reply(args.A + args.B)
|
||||
return nil
|
||||
})
|
||||
|
||||
lis, _ := net.Listen("tcp", "127.0.0.1:5000")
|
||||
srv.Accept(lis)
|
||||
}
|
||||
```
|
||||
|
||||
Example Client
|
||||
---------------
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/cenkalti/rpc2"
|
||||
)
|
||||
|
||||
type Args struct{ A, B int }
|
||||
type Reply int
|
||||
|
||||
func main() {
|
||||
conn, _ := net.Dial("tcp", "127.0.0.1:5000")
|
||||
|
||||
clt := rpc2.NewClient(conn)
|
||||
clt.Handle("mult", func(client *rpc2.Client, args *Args, reply *Reply) error {
|
||||
*reply = Reply(args.A * args.B)
|
||||
return nil
|
||||
})
|
||||
go clt.Run()
|
||||
|
||||
var rep Reply
|
||||
clt.Call("add", Args{1, 2}, &rep)
|
||||
fmt.Println("add result:", rep)
|
||||
}
|
||||
```
|
364
vendor/github.com/cenkalti/rpc2/client.go
generated
vendored
364
vendor/github.com/cenkalti/rpc2/client.go
generated
vendored
@@ -1,364 +0,0 @@
|
||||
// Package rpc2 provides bi-directional RPC client and server similar to net/rpc.
|
||||
package rpc2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Client represents an RPC Client.
|
||||
// There may be multiple outstanding Calls associated
|
||||
// with a single Client, and a Client may be used by
|
||||
// multiple goroutines simultaneously.
|
||||
type Client struct {
|
||||
mutex sync.Mutex // protects pending, seq, request
|
||||
sending sync.Mutex
|
||||
request Request // temp area used in send()
|
||||
seq uint64
|
||||
pending map[uint64]*Call
|
||||
closing bool
|
||||
shutdown bool
|
||||
server bool
|
||||
codec Codec
|
||||
handlers map[string]*handler
|
||||
disconnect chan struct{}
|
||||
State *State // additional information to associate with client
|
||||
blocking bool // whether to block request handling
|
||||
}
|
||||
|
||||
// NewClient returns a new Client to handle requests to the
|
||||
// set of services at the other end of the connection.
|
||||
// It adds a buffer to the write side of the connection so
|
||||
// the header and payload are sent as a unit.
|
||||
func NewClient(conn io.ReadWriteCloser) *Client {
|
||||
return NewClientWithCodec(NewGobCodec(conn))
|
||||
}
|
||||
|
||||
// NewClientWithCodec is like NewClient but uses the specified
|
||||
// codec to encode requests and decode responses.
|
||||
func NewClientWithCodec(codec Codec) *Client {
|
||||
return &Client{
|
||||
codec: codec,
|
||||
pending: make(map[uint64]*Call),
|
||||
handlers: make(map[string]*handler),
|
||||
disconnect: make(chan struct{}),
|
||||
seq: 1, // 0 means notification.
|
||||
}
|
||||
}
|
||||
|
||||
// SetBlocking puts the client in blocking mode.
|
||||
// In blocking mode, received requests are processes synchronously.
|
||||
// If you have methods that may take a long time, other subsequent requests may time out.
|
||||
func (c *Client) SetBlocking(blocking bool) {
|
||||
c.blocking = blocking
|
||||
}
|
||||
|
||||
// Run the client's read loop.
|
||||
// You must run this method before calling any methods on the server.
|
||||
func (c *Client) Run() {
|
||||
c.readLoop()
|
||||
}
|
||||
|
||||
// DisconnectNotify returns a channel that is closed
|
||||
// when the client connection has gone away.
|
||||
func (c *Client) DisconnectNotify() chan struct{} {
|
||||
return c.disconnect
|
||||
}
|
||||
|
||||
// Handle registers the handler function for the given method. If a handler already exists for method, Handle panics.
|
||||
func (c *Client) Handle(method string, handlerFunc interface{}) {
|
||||
addHandler(c.handlers, method, handlerFunc)
|
||||
}
|
||||
|
||||
// readLoop reads messages from codec.
|
||||
// It reads a reqeust or a response to the previous request.
|
||||
// If the message is request, calls the handler function.
|
||||
// If the message is response, sends the reply to the associated call.
|
||||
func (c *Client) readLoop() {
|
||||
var err error
|
||||
var req Request
|
||||
var resp Response
|
||||
for err == nil {
|
||||
req = Request{}
|
||||
resp = Response{}
|
||||
if err = c.codec.ReadHeader(&req, &resp); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if req.Method != "" {
|
||||
// request comes to server
|
||||
if err = c.readRequest(&req); err != nil {
|
||||
debugln("rpc2: error reading request:", err.Error())
|
||||
}
|
||||
} else {
|
||||
// response comes to client
|
||||
if err = c.readResponse(&resp); err != nil {
|
||||
debugln("rpc2: error reading response:", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
// Terminate pending calls.
|
||||
c.sending.Lock()
|
||||
c.mutex.Lock()
|
||||
c.shutdown = true
|
||||
closing := c.closing
|
||||
if err == io.EOF {
|
||||
if closing {
|
||||
err = ErrShutdown
|
||||
} else {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
for _, call := range c.pending {
|
||||
call.Error = err
|
||||
call.done()
|
||||
}
|
||||
c.mutex.Unlock()
|
||||
c.sending.Unlock()
|
||||
if err != io.EOF && !closing && !c.server {
|
||||
debugln("rpc2: client protocol error:", err)
|
||||
}
|
||||
close(c.disconnect)
|
||||
if !closing {
|
||||
c.codec.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) handleRequest(req Request, method *handler, argv reflect.Value) {
|
||||
// Invoke the method, providing a new value for the reply.
|
||||
replyv := reflect.New(method.replyType.Elem())
|
||||
|
||||
returnValues := method.fn.Call([]reflect.Value{reflect.ValueOf(c), argv, replyv})
|
||||
|
||||
// Do not send response if request is a notification.
|
||||
if req.Seq == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// The return value for the method is an error.
|
||||
errInter := returnValues[0].Interface()
|
||||
errmsg := ""
|
||||
if errInter != nil {
|
||||
errmsg = errInter.(error).Error()
|
||||
}
|
||||
resp := &Response{
|
||||
Seq: req.Seq,
|
||||
Error: errmsg,
|
||||
}
|
||||
if err := c.codec.WriteResponse(resp, replyv.Interface()); err != nil {
|
||||
debugln("rpc2: error writing response:", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) readRequest(req *Request) error {
|
||||
method, ok := c.handlers[req.Method]
|
||||
if !ok {
|
||||
resp := &Response{
|
||||
Seq: req.Seq,
|
||||
Error: "rpc2: can't find method " + req.Method,
|
||||
}
|
||||
return c.codec.WriteResponse(resp, resp)
|
||||
}
|
||||
|
||||
// Decode the argument value.
|
||||
var argv reflect.Value
|
||||
argIsValue := false // if true, need to indirect before calling.
|
||||
if method.argType.Kind() == reflect.Ptr {
|
||||
argv = reflect.New(method.argType.Elem())
|
||||
} else {
|
||||
argv = reflect.New(method.argType)
|
||||
argIsValue = true
|
||||
}
|
||||
// argv guaranteed to be a pointer now.
|
||||
if err := c.codec.ReadRequestBody(argv.Interface()); err != nil {
|
||||
return err
|
||||
}
|
||||
if argIsValue {
|
||||
argv = argv.Elem()
|
||||
}
|
||||
|
||||
if c.blocking {
|
||||
c.handleRequest(*req, method, argv)
|
||||
} else {
|
||||
go c.handleRequest(*req, method, argv)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) readResponse(resp *Response) error {
|
||||
seq := resp.Seq
|
||||
c.mutex.Lock()
|
||||
call := c.pending[seq]
|
||||
delete(c.pending, seq)
|
||||
c.mutex.Unlock()
|
||||
|
||||
var err error
|
||||
switch {
|
||||
case call == nil:
|
||||
// We've got no pending call. That usually means that
|
||||
// WriteRequest partially failed, and call was already
|
||||
// removed; response is a server telling us about an
|
||||
// error reading request body. We should still attempt
|
||||
// to read error body, but there's no one to give it to.
|
||||
err = c.codec.ReadResponseBody(nil)
|
||||
if err != nil {
|
||||
err = errors.New("reading error body: " + err.Error())
|
||||
}
|
||||
case resp.Error != "":
|
||||
// We've got an error response. Give this to the request;
|
||||
// any subsequent requests will get the ReadResponseBody
|
||||
// error if there is one.
|
||||
call.Error = ServerError(resp.Error)
|
||||
err = c.codec.ReadResponseBody(nil)
|
||||
if err != nil {
|
||||
err = errors.New("reading error body: " + err.Error())
|
||||
}
|
||||
call.done()
|
||||
default:
|
||||
err = c.codec.ReadResponseBody(call.Reply)
|
||||
if err != nil {
|
||||
call.Error = errors.New("reading body " + err.Error())
|
||||
}
|
||||
call.done()
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Close waits for active calls to finish and closes the codec.
|
||||
func (c *Client) Close() error {
|
||||
c.mutex.Lock()
|
||||
if c.shutdown || c.closing {
|
||||
c.mutex.Unlock()
|
||||
return ErrShutdown
|
||||
}
|
||||
c.closing = true
|
||||
c.mutex.Unlock()
|
||||
return c.codec.Close()
|
||||
}
|
||||
|
||||
// Go invokes the function asynchronously. It returns the Call structure representing
|
||||
// the invocation. The done channel will signal when the call is complete by returning
|
||||
// the same Call object. If done is nil, Go will allocate a new channel.
|
||||
// If non-nil, done must be buffered or Go will deliberately crash.
|
||||
func (c *Client) Go(method string, args interface{}, reply interface{}, done chan *Call) *Call {
|
||||
call := new(Call)
|
||||
call.Method = method
|
||||
call.Args = args
|
||||
call.Reply = reply
|
||||
if done == nil {
|
||||
done = make(chan *Call, 10) // buffered.
|
||||
} else {
|
||||
// If caller passes done != nil, it must arrange that
|
||||
// done has enough buffer for the number of simultaneous
|
||||
// RPCs that will be using that channel. If the channel
|
||||
// is totally unbuffered, it's best not to run at all.
|
||||
if cap(done) == 0 {
|
||||
log.Panic("rpc2: done channel is unbuffered")
|
||||
}
|
||||
}
|
||||
call.Done = done
|
||||
c.send(call)
|
||||
return call
|
||||
}
|
||||
|
||||
// CallWithContext invokes the named function, waits for it to complete, and
|
||||
// returns its error status, or an error from Context timeout.
|
||||
func (c *Client) CallWithContext(ctx context.Context, method string, args interface{}, reply interface{}) error {
|
||||
call := c.Go(method, args, reply, make(chan *Call, 1))
|
||||
select {
|
||||
case <-call.Done:
|
||||
return call.Error
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Call invokes the named function, waits for it to complete, and returns its error status.
|
||||
func (c *Client) Call(method string, args interface{}, reply interface{}) error {
|
||||
return c.CallWithContext(context.Background(), method, args, reply)
|
||||
}
|
||||
|
||||
func (call *Call) done() {
|
||||
select {
|
||||
case call.Done <- call:
|
||||
// ok
|
||||
default:
|
||||
// We don't want to block here. It is the caller's responsibility to make
|
||||
// sure the channel has enough buffer space. See comment in Go().
|
||||
debugln("rpc2: discarding Call reply due to insufficient Done chan capacity")
|
||||
}
|
||||
}
|
||||
|
||||
// ServerError represents an error that has been returned from
|
||||
// the remote side of the RPC connection.
|
||||
type ServerError string
|
||||
|
||||
func (e ServerError) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
// ErrShutdown is returned when the connection is closing or closed.
|
||||
var ErrShutdown = errors.New("connection is shut down")
|
||||
|
||||
// Call represents an active RPC.
|
||||
type Call struct {
|
||||
Method string // The name of the service and method to call.
|
||||
Args interface{} // The argument to the function (*struct).
|
||||
Reply interface{} // The reply from the function (*struct).
|
||||
Error error // After completion, the error status.
|
||||
Done chan *Call // Strobes when call is complete.
|
||||
}
|
||||
|
||||
func (c *Client) send(call *Call) {
|
||||
c.sending.Lock()
|
||||
defer c.sending.Unlock()
|
||||
|
||||
// Register this call.
|
||||
c.mutex.Lock()
|
||||
if c.shutdown || c.closing {
|
||||
call.Error = ErrShutdown
|
||||
c.mutex.Unlock()
|
||||
call.done()
|
||||
return
|
||||
}
|
||||
seq := c.seq
|
||||
c.seq++
|
||||
c.pending[seq] = call
|
||||
c.mutex.Unlock()
|
||||
|
||||
// Encode and send the request.
|
||||
c.request.Seq = seq
|
||||
c.request.Method = call.Method
|
||||
err := c.codec.WriteRequest(&c.request, call.Args)
|
||||
if err != nil {
|
||||
c.mutex.Lock()
|
||||
call = c.pending[seq]
|
||||
delete(c.pending, seq)
|
||||
c.mutex.Unlock()
|
||||
if call != nil {
|
||||
call.Error = err
|
||||
call.done()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify sends a request to the receiver but does not wait for a return value.
|
||||
func (c *Client) Notify(method string, args interface{}) error {
|
||||
c.sending.Lock()
|
||||
defer c.sending.Unlock()
|
||||
|
||||
if c.shutdown || c.closing {
|
||||
return ErrShutdown
|
||||
}
|
||||
|
||||
c.request.Seq = 0
|
||||
c.request.Method = method
|
||||
return c.codec.WriteRequest(&c.request, args)
|
||||
}
|
125
vendor/github.com/cenkalti/rpc2/codec.go
generated
vendored
125
vendor/github.com/cenkalti/rpc2/codec.go
generated
vendored
@@ -1,125 +0,0 @@
|
||||
package rpc2
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/gob"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A Codec implements reading and writing of RPC requests and responses.
|
||||
// The client calls ReadHeader to read a message header.
|
||||
// The implementation must populate either Request or Response argument.
|
||||
// Depending on which argument is populated, ReadRequestBody or
|
||||
// ReadResponseBody is called right after ReadHeader.
|
||||
// ReadRequestBody and ReadResponseBody may be called with a nil
|
||||
// argument to force the body to be read and then discarded.
|
||||
type Codec interface {
|
||||
// ReadHeader must read a message and populate either the request
|
||||
// or the response by inspecting the incoming message.
|
||||
ReadHeader(*Request, *Response) error
|
||||
|
||||
// ReadRequestBody into args argument of handler function.
|
||||
ReadRequestBody(interface{}) error
|
||||
|
||||
// ReadResponseBody into reply argument of handler function.
|
||||
ReadResponseBody(interface{}) error
|
||||
|
||||
// WriteRequest must be safe for concurrent use by multiple goroutines.
|
||||
WriteRequest(*Request, interface{}) error
|
||||
|
||||
// WriteResponse must be safe for concurrent use by multiple goroutines.
|
||||
WriteResponse(*Response, interface{}) error
|
||||
|
||||
// Close is called when client/server finished with the connection.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Request is a header written before every RPC call.
|
||||
type Request struct {
|
||||
Seq uint64 // sequence number chosen by client
|
||||
Method string
|
||||
}
|
||||
|
||||
// Response is a header written before every RPC return.
|
||||
type Response struct {
|
||||
Seq uint64 // echoes that of the request
|
||||
Error string // error, if any.
|
||||
}
|
||||
|
||||
type gobCodec struct {
|
||||
rwc io.ReadWriteCloser
|
||||
dec *gob.Decoder
|
||||
enc *gob.Encoder
|
||||
encBuf *bufio.Writer
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
type message struct {
|
||||
Seq uint64
|
||||
Method string
|
||||
Error string
|
||||
}
|
||||
|
||||
// NewGobCodec returns a new rpc2.Codec using gob encoding/decoding on conn.
|
||||
func NewGobCodec(conn io.ReadWriteCloser) Codec {
|
||||
buf := bufio.NewWriter(conn)
|
||||
return &gobCodec{
|
||||
rwc: conn,
|
||||
dec: gob.NewDecoder(conn),
|
||||
enc: gob.NewEncoder(buf),
|
||||
encBuf: buf,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *gobCodec) ReadHeader(req *Request, resp *Response) error {
|
||||
var msg message
|
||||
if err := c.dec.Decode(&msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if msg.Method != "" {
|
||||
req.Seq = msg.Seq
|
||||
req.Method = msg.Method
|
||||
} else {
|
||||
resp.Seq = msg.Seq
|
||||
resp.Error = msg.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *gobCodec) ReadRequestBody(body interface{}) error {
|
||||
return c.dec.Decode(body)
|
||||
}
|
||||
|
||||
func (c *gobCodec) ReadResponseBody(body interface{}) error {
|
||||
return c.dec.Decode(body)
|
||||
}
|
||||
|
||||
func (c *gobCodec) WriteRequest(r *Request, body interface{}) (err error) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
if err = c.enc.Encode(r); err != nil {
|
||||
return
|
||||
}
|
||||
if err = c.enc.Encode(body); err != nil {
|
||||
return
|
||||
}
|
||||
return c.encBuf.Flush()
|
||||
}
|
||||
|
||||
func (c *gobCodec) WriteResponse(r *Response, body interface{}) (err error) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
if err = c.enc.Encode(r); err != nil {
|
||||
return
|
||||
}
|
||||
if err = c.enc.Encode(body); err != nil {
|
||||
return
|
||||
}
|
||||
return c.encBuf.Flush()
|
||||
}
|
||||
|
||||
func (c *gobCodec) Close() error {
|
||||
return c.rwc.Close()
|
||||
}
|
12
vendor/github.com/cenkalti/rpc2/debug.go
generated
vendored
12
vendor/github.com/cenkalti/rpc2/debug.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
package rpc2
|
||||
|
||||
import "log"
|
||||
|
||||
// DebugLog controls the printing of internal and I/O errors.
|
||||
var DebugLog = false
|
||||
|
||||
func debugln(v ...interface{}) {
|
||||
if DebugLog {
|
||||
log.Println(v...)
|
||||
}
|
||||
}
|
226
vendor/github.com/cenkalti/rpc2/jsonrpc/jsonrpc.go
generated
vendored
226
vendor/github.com/cenkalti/rpc2/jsonrpc/jsonrpc.go
generated
vendored
@@ -1,226 +0,0 @@
|
||||
// Package jsonrpc implements a JSON-RPC ClientCodec and ServerCodec for the rpc2 package.
|
||||
//
|
||||
// Beside struct types, JSONCodec allows using positional arguments.
|
||||
// Use []interface{} as the type of argument when sending and receiving methods.
|
||||
//
|
||||
// Positional arguments example:
|
||||
// server.Handle("add", func(client *rpc2.Client, args []interface{}, result *float64) error {
|
||||
// *result = args[0].(float64) + args[1].(float64)
|
||||
// return nil
|
||||
// })
|
||||
//
|
||||
// var result float64
|
||||
// client.Call("add", []interface{}{1, 2}, &result)
|
||||
//
|
||||
package jsonrpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/cenkalti/rpc2"
|
||||
)
|
||||
|
||||
type jsonCodec struct {
|
||||
dec *json.Decoder // for reading JSON values
|
||||
enc *json.Encoder // for writing JSON values
|
||||
c io.Closer
|
||||
|
||||
// temporary work space
|
||||
msg message
|
||||
serverRequest serverRequest
|
||||
clientResponse clientResponse
|
||||
|
||||
// JSON-RPC clients can use arbitrary json values as request IDs.
|
||||
// Package rpc expects uint64 request IDs.
|
||||
// We assign uint64 sequence numbers to incoming requests
|
||||
// but save the original request ID in the pending map.
|
||||
// When rpc responds, we use the sequence number in
|
||||
// the response to find the original request ID.
|
||||
mutex sync.Mutex // protects seq, pending
|
||||
pending map[uint64]*json.RawMessage
|
||||
seq uint64
|
||||
}
|
||||
|
||||
// NewJSONCodec returns a new rpc2.Codec using JSON-RPC on conn.
|
||||
func NewJSONCodec(conn io.ReadWriteCloser) rpc2.Codec {
|
||||
return &jsonCodec{
|
||||
dec: json.NewDecoder(conn),
|
||||
enc: json.NewEncoder(conn),
|
||||
c: conn,
|
||||
pending: make(map[uint64]*json.RawMessage),
|
||||
}
|
||||
}
|
||||
|
||||
// serverRequest and clientResponse combined
|
||||
type message struct {
|
||||
Method string `json:"method"`
|
||||
Params *json.RawMessage `json:"params"`
|
||||
Id *json.RawMessage `json:"id"`
|
||||
Result *json.RawMessage `json:"result"`
|
||||
Error interface{} `json:"error"`
|
||||
}
|
||||
|
||||
// Unmarshal to
|
||||
type serverRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params *json.RawMessage `json:"params"`
|
||||
Id *json.RawMessage `json:"id"`
|
||||
}
|
||||
type clientResponse struct {
|
||||
Id uint64 `json:"id"`
|
||||
Result *json.RawMessage `json:"result"`
|
||||
Error interface{} `json:"error"`
|
||||
}
|
||||
|
||||
// to Marshal
|
||||
type serverResponse struct {
|
||||
Id *json.RawMessage `json:"id"`
|
||||
Result interface{} `json:"result"`
|
||||
Error interface{} `json:"error"`
|
||||
}
|
||||
type clientRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params interface{} `json:"params"`
|
||||
Id *uint64 `json:"id"`
|
||||
}
|
||||
|
||||
func (c *jsonCodec) ReadHeader(req *rpc2.Request, resp *rpc2.Response) error {
|
||||
c.msg = message{}
|
||||
if err := c.dec.Decode(&c.msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.msg.Method != "" {
|
||||
// request comes to server
|
||||
c.serverRequest.Id = c.msg.Id
|
||||
c.serverRequest.Method = c.msg.Method
|
||||
c.serverRequest.Params = c.msg.Params
|
||||
|
||||
req.Method = c.serverRequest.Method
|
||||
|
||||
// JSON request id can be any JSON value;
|
||||
// RPC package expects uint64. Translate to
|
||||
// internal uint64 and save JSON on the side.
|
||||
if c.serverRequest.Id == nil {
|
||||
// Notification
|
||||
} else {
|
||||
c.mutex.Lock()
|
||||
c.seq++
|
||||
c.pending[c.seq] = c.serverRequest.Id
|
||||
c.serverRequest.Id = nil
|
||||
req.Seq = c.seq
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
} else {
|
||||
// response comes to client
|
||||
err := json.Unmarshal(*c.msg.Id, &c.clientResponse.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.clientResponse.Result = c.msg.Result
|
||||
c.clientResponse.Error = c.msg.Error
|
||||
|
||||
resp.Error = ""
|
||||
resp.Seq = c.clientResponse.Id
|
||||
if c.clientResponse.Error != nil || c.clientResponse.Result == nil {
|
||||
x, ok := c.clientResponse.Error.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid error %v", c.clientResponse.Error)
|
||||
}
|
||||
if x == "" {
|
||||
x = "unspecified error"
|
||||
}
|
||||
resp.Error = x
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var errMissingParams = errors.New("jsonrpc: request body missing params")
|
||||
|
||||
func (c *jsonCodec) ReadRequestBody(x interface{}) error {
|
||||
if x == nil {
|
||||
return nil
|
||||
}
|
||||
if c.serverRequest.Params == nil {
|
||||
return errMissingParams
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
// Check if x points to a slice of any kind
|
||||
rt := reflect.TypeOf(x)
|
||||
if rt.Kind() == reflect.Ptr && rt.Elem().Kind() == reflect.Slice {
|
||||
// If it's a slice, unmarshal as is
|
||||
err = json.Unmarshal(*c.serverRequest.Params, x)
|
||||
} else {
|
||||
// Anything else unmarshal into a slice containing x
|
||||
params := &[]interface{}{x}
|
||||
err = json.Unmarshal(*c.serverRequest.Params, params)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *jsonCodec) ReadResponseBody(x interface{}) error {
|
||||
if x == nil {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(*c.clientResponse.Result, x)
|
||||
}
|
||||
|
||||
func (c *jsonCodec) WriteRequest(r *rpc2.Request, param interface{}) error {
|
||||
req := &clientRequest{Method: r.Method}
|
||||
|
||||
// Check if param is a slice of any kind
|
||||
if param != nil && reflect.TypeOf(param).Kind() == reflect.Slice {
|
||||
// If it's a slice, leave as is
|
||||
req.Params = param
|
||||
} else {
|
||||
// Put anything else into a slice
|
||||
req.Params = []interface{}{param}
|
||||
}
|
||||
|
||||
if r.Seq == 0 {
|
||||
// Notification
|
||||
req.Id = nil
|
||||
} else {
|
||||
seq := r.Seq
|
||||
req.Id = &seq
|
||||
}
|
||||
return c.enc.Encode(req)
|
||||
}
|
||||
|
||||
var null = json.RawMessage([]byte("null"))
|
||||
|
||||
func (c *jsonCodec) WriteResponse(r *rpc2.Response, x interface{}) error {
|
||||
c.mutex.Lock()
|
||||
b, ok := c.pending[r.Seq]
|
||||
if !ok {
|
||||
c.mutex.Unlock()
|
||||
return errors.New("invalid sequence number in response")
|
||||
}
|
||||
delete(c.pending, r.Seq)
|
||||
c.mutex.Unlock()
|
||||
|
||||
if b == nil {
|
||||
// Invalid request so no id. Use JSON null.
|
||||
b = &null
|
||||
}
|
||||
resp := serverResponse{Id: b}
|
||||
if r.Error == "" {
|
||||
resp.Result = x
|
||||
} else {
|
||||
resp.Error = r.Error
|
||||
}
|
||||
return c.enc.Encode(resp)
|
||||
}
|
||||
|
||||
func (c *jsonCodec) Close() error {
|
||||
return c.c.Close()
|
||||
}
|
181
vendor/github.com/cenkalti/rpc2/server.go
generated
vendored
181
vendor/github.com/cenkalti/rpc2/server.go
generated
vendored
@@ -1,181 +0,0 @@
|
||||
package rpc2
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"reflect"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/cenkalti/hub"
|
||||
)
|
||||
|
||||
// Precompute the reflect type for error. Can't use error directly
|
||||
// because Typeof takes an empty interface value. This is annoying.
|
||||
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
|
||||
var typeOfClient = reflect.TypeOf((*Client)(nil))
|
||||
|
||||
const (
|
||||
clientConnected hub.Kind = iota
|
||||
clientDisconnected
|
||||
)
|
||||
|
||||
// Server responds to RPC requests made by Client.
|
||||
type Server struct {
|
||||
handlers map[string]*handler
|
||||
eventHub *hub.Hub
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
fn reflect.Value
|
||||
argType reflect.Type
|
||||
replyType reflect.Type
|
||||
}
|
||||
|
||||
type connectionEvent struct {
|
||||
Client *Client
|
||||
}
|
||||
|
||||
type disconnectionEvent struct {
|
||||
Client *Client
|
||||
}
|
||||
|
||||
func (connectionEvent) Kind() hub.Kind { return clientConnected }
|
||||
func (disconnectionEvent) Kind() hub.Kind { return clientDisconnected }
|
||||
|
||||
// NewServer returns a new Server.
|
||||
func NewServer() *Server {
|
||||
return &Server{
|
||||
handlers: make(map[string]*handler),
|
||||
eventHub: &hub.Hub{},
|
||||
}
|
||||
}
|
||||
|
||||
// Handle registers the handler function for the given method. If a handler already exists for method, Handle panics.
|
||||
func (s *Server) Handle(method string, handlerFunc interface{}) {
|
||||
addHandler(s.handlers, method, handlerFunc)
|
||||
}
|
||||
|
||||
func addHandler(handlers map[string]*handler, mname string, handlerFunc interface{}) {
|
||||
if _, ok := handlers[mname]; ok {
|
||||
panic("rpc2: multiple registrations for " + mname)
|
||||
}
|
||||
|
||||
method := reflect.ValueOf(handlerFunc)
|
||||
mtype := method.Type()
|
||||
// Method needs three ins: *client, *args, *reply.
|
||||
if mtype.NumIn() != 3 {
|
||||
log.Panicln("method", mname, "has wrong number of ins:", mtype.NumIn())
|
||||
}
|
||||
// First arg must be a pointer to rpc2.Client.
|
||||
clientType := mtype.In(0)
|
||||
if clientType.Kind() != reflect.Ptr {
|
||||
log.Panicln("method", mname, "client type not a pointer:", clientType)
|
||||
}
|
||||
if clientType != typeOfClient {
|
||||
log.Panicln("method", mname, "first argument", clientType.String(), "not *rpc2.Client")
|
||||
}
|
||||
// Second arg need not be a pointer.
|
||||
argType := mtype.In(1)
|
||||
if !isExportedOrBuiltinType(argType) {
|
||||
log.Panicln(mname, "argument type not exported:", argType)
|
||||
}
|
||||
// Third arg must be a pointer.
|
||||
replyType := mtype.In(2)
|
||||
if replyType.Kind() != reflect.Ptr {
|
||||
log.Panicln("method", mname, "reply type not a pointer:", replyType)
|
||||
}
|
||||
// Reply type must be exported.
|
||||
if !isExportedOrBuiltinType(replyType) {
|
||||
log.Panicln("method", mname, "reply type not exported:", replyType)
|
||||
}
|
||||
// Method needs one out.
|
||||
if mtype.NumOut() != 1 {
|
||||
log.Panicln("method", mname, "has wrong number of outs:", mtype.NumOut())
|
||||
}
|
||||
// The return type of the method must be error.
|
||||
if returnType := mtype.Out(0); returnType != typeOfError {
|
||||
log.Panicln("method", mname, "returns", returnType.String(), "not error")
|
||||
}
|
||||
handlers[mname] = &handler{
|
||||
fn: method,
|
||||
argType: argType,
|
||||
replyType: replyType,
|
||||
}
|
||||
}
|
||||
|
||||
// Is this type exported or a builtin?
|
||||
func isExportedOrBuiltinType(t reflect.Type) bool {
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
// PkgPath will be non-empty even for an exported type,
|
||||
// so we need to check the type name as well.
|
||||
return isExported(t.Name()) || t.PkgPath() == ""
|
||||
}
|
||||
|
||||
// Is this an exported - upper case - name?
|
||||
func isExported(name string) bool {
|
||||
rune, _ := utf8.DecodeRuneInString(name)
|
||||
return unicode.IsUpper(rune)
|
||||
}
|
||||
|
||||
// OnConnect registers a function to run when a client connects.
|
||||
func (s *Server) OnConnect(f func(*Client)) {
|
||||
s.eventHub.Subscribe(clientConnected, func(e hub.Event) {
|
||||
go f(e.(connectionEvent).Client)
|
||||
})
|
||||
}
|
||||
|
||||
// OnDisconnect registers a function to run when a client disconnects.
|
||||
func (s *Server) OnDisconnect(f func(*Client)) {
|
||||
s.eventHub.Subscribe(clientDisconnected, func(e hub.Event) {
|
||||
go f(e.(disconnectionEvent).Client)
|
||||
})
|
||||
}
|
||||
|
||||
// Accept accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func (s *Server) Accept(lis net.Listener) {
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Print("rpc.Serve: accept:", err.Error())
|
||||
return
|
||||
}
|
||||
go s.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// ServeConn runs the server on a single connection.
|
||||
// ServeConn blocks, serving the connection until the client hangs up.
|
||||
// The caller typically invokes ServeConn in a go statement.
|
||||
// ServeConn uses the gob wire format (see package gob) on the
|
||||
// connection. To use an alternate codec, use ServeCodec.
|
||||
func (s *Server) ServeConn(conn io.ReadWriteCloser) {
|
||||
s.ServeCodec(NewGobCodec(conn))
|
||||
}
|
||||
|
||||
// ServeCodec is like ServeConn but uses the specified codec to
|
||||
// decode requests and encode responses.
|
||||
func (s *Server) ServeCodec(codec Codec) {
|
||||
s.ServeCodecWithState(codec, NewState())
|
||||
}
|
||||
|
||||
// ServeCodecWithState is like ServeCodec but also gives the ability to
|
||||
// associate a state variable with the client that persists across RPC calls.
|
||||
func (s *Server) ServeCodecWithState(codec Codec, state *State) {
|
||||
defer codec.Close()
|
||||
|
||||
// Client also handles the incoming connections.
|
||||
c := NewClientWithCodec(codec)
|
||||
c.server = true
|
||||
c.handlers = s.handlers
|
||||
c.State = state
|
||||
|
||||
s.eventHub.Publish(connectionEvent{c})
|
||||
c.Run()
|
||||
s.eventHub.Publish(disconnectionEvent{c})
|
||||
}
|
25
vendor/github.com/cenkalti/rpc2/state.go
generated
vendored
25
vendor/github.com/cenkalti/rpc2/state.go
generated
vendored
@@ -1,25 +0,0 @@
|
||||
package rpc2
|
||||
|
||||
import "sync"
|
||||
|
||||
type State struct {
|
||||
store map[string]interface{}
|
||||
m sync.RWMutex
|
||||
}
|
||||
|
||||
func NewState() *State {
|
||||
return &State{store: make(map[string]interface{})}
|
||||
}
|
||||
|
||||
func (s *State) Get(key string) (value interface{}, ok bool) {
|
||||
s.m.RLock()
|
||||
value, ok = s.store[key]
|
||||
s.m.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (s *State) Set(key string, value interface{}) {
|
||||
s.m.Lock()
|
||||
s.store[key] = value
|
||||
s.m.Unlock()
|
||||
}
|
6
vendor/github.com/go-logr/logr/CHANGELOG.md
generated
vendored
6
vendor/github.com/go-logr/logr/CHANGELOG.md
generated
vendored
@@ -1,6 +0,0 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v1.0.0-rc1
|
||||
|
||||
This is the first logged release. Major changes (including breaking changes)
|
||||
have occurred since earlier tags.
|
17
vendor/github.com/go-logr/logr/CONTRIBUTING.md
generated
vendored
17
vendor/github.com/go-logr/logr/CONTRIBUTING.md
generated
vendored
@@ -1,17 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
Logr is open to pull-requests, provided they fit within the intended scope of
|
||||
the project. Specifically, this library aims to be VERY small and minimalist,
|
||||
with no external dependencies.
|
||||
|
||||
## Compatibility
|
||||
|
||||
This project intends to follow [semantic versioning](http://semver.org) and
|
||||
is very strict about compatibility. Any proposed changes MUST follow those
|
||||
rules.
|
||||
|
||||
## Performance
|
||||
|
||||
As a logging library, logr must be as light-weight as possible. Any proposed
|
||||
code change must include results of running the [benchmark](./benchmark)
|
||||
before and after the change.
|
201
vendor/github.com/go-logr/logr/LICENSE
generated
vendored
201
vendor/github.com/go-logr/logr/LICENSE
generated
vendored
@@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
275
vendor/github.com/go-logr/logr/README.md
generated
vendored
275
vendor/github.com/go-logr/logr/README.md
generated
vendored
@@ -1,275 +0,0 @@
|
||||
# A minimal logging API for Go
|
||||
|
||||
logr offers an(other) opinion on how Go programs and libraries can do logging
|
||||
without becoming coupled to a particular logging implementation. This is not
|
||||
an implementation of logging - it is an API. In fact it is two APIs with two
|
||||
different sets of users.
|
||||
|
||||
The `Logger` type is intended for application and library authors. It provides
|
||||
a relatively small API which can be used everywhere you want to emit logs. It
|
||||
defers the actual act of writing logs (to files, to stdout, or whatever) to the
|
||||
`LogSink` interface.
|
||||
|
||||
The `LogSink` interface is intended for logging library implementers. It is a
|
||||
pure interface which can be implemented by logging frameworks to provide the actual logging
|
||||
functionality.
|
||||
|
||||
This decoupling allows application and library developers to write code in
|
||||
terms of `logr.Logger` (which has very low dependency fan-out) while the
|
||||
implementation of logging is managed "up stack" (e.g. in or near `main()`.)
|
||||
Application developers can then switch out implementations as necessary.
|
||||
|
||||
Many people assert that libraries should not be logging, and as such efforts
|
||||
like this are pointless. Those people are welcome to convince the authors of
|
||||
the tens-of-thousands of libraries that *DO* write logs that they are all
|
||||
wrong. In the meantime, logr takes a more practical approach.
|
||||
|
||||
## Typical usage
|
||||
|
||||
Somewhere, early in an application's life, it will make a decision about which
|
||||
logging library (implementation) it actually wants to use. Something like:
|
||||
|
||||
```
|
||||
func main() {
|
||||
// ... other setup code ...
|
||||
|
||||
// Create the "root" logger. We have chosen the "logimpl" implementation,
|
||||
// which takes some initial parameters and returns a logr.Logger.
|
||||
logger := logimpl.New(param1, param2)
|
||||
|
||||
// ... other setup code ...
|
||||
```
|
||||
|
||||
Most apps will call into other libraries, create structures to govern the flow,
|
||||
etc. The `logr.Logger` object can be passed to these other libraries, stored
|
||||
in structs, or even used as a package-global variable, if needed. For example:
|
||||
|
||||
```
|
||||
app := createTheAppObject(logger)
|
||||
app.Run()
|
||||
```
|
||||
|
||||
Outside of this early setup, no other packages need to know about the choice of
|
||||
implementation. They write logs in terms of the `logr.Logger` that they
|
||||
received:
|
||||
|
||||
```
|
||||
type appObject struct {
|
||||
// ... other fields ...
|
||||
logger logr.Logger
|
||||
// ... other fields ...
|
||||
}
|
||||
|
||||
func (app *appObject) Run() {
|
||||
app.logger.Info("starting up", "timestamp", time.Now())
|
||||
|
||||
// ... app code ...
|
||||
```
|
||||
|
||||
## Background
|
||||
|
||||
If the Go standard library had defined an interface for logging, this project
|
||||
probably would not be needed. Alas, here we are.
|
||||
|
||||
### Inspiration
|
||||
|
||||
Before you consider this package, please read [this blog post by the
|
||||
inimitable Dave Cheney][warning-makes-no-sense]. We really appreciate what
|
||||
he has to say, and it largely aligns with our own experiences.
|
||||
|
||||
### Differences from Dave's ideas
|
||||
|
||||
The main differences are:
|
||||
|
||||
1. Dave basically proposes doing away with the notion of a logging API in favor
|
||||
of `fmt.Printf()`. We disagree, especially when you consider things like output
|
||||
locations, timestamps, file and line decorations, and structured logging. This
|
||||
package restricts the logging API to just 2 types of logs: info and error.
|
||||
|
||||
Info logs are things you want to tell the user which are not errors. Error
|
||||
logs are, well, errors. If your code receives an `error` from a subordinate
|
||||
function call and is logging that `error` *and not returning it*, use error
|
||||
logs.
|
||||
|
||||
2. Verbosity-levels on info logs. This gives developers a chance to indicate
|
||||
arbitrary grades of importance for info logs, without assigning names with
|
||||
semantic meaning such as "warning", "trace", and "debug." Superficially this
|
||||
may feel very similar, but the primary difference is the lack of semantics.
|
||||
Because verbosity is a numerical value, it's safe to assume that an app running
|
||||
with higher verbosity means more (and less important) logs will be generated.
|
||||
|
||||
## Implementations (non-exhaustive)
|
||||
|
||||
There are implementations for the following logging libraries:
|
||||
|
||||
- **a function**: [funcr](https://github.com/go-logr/logr/tree/master/funcr)
|
||||
- **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr)
|
||||
- **k8s.io/klog**: [klogr](https://git.k8s.io/klog/klogr)
|
||||
- **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr)
|
||||
- **log** (the Go standard library logger): [stdr](https://github.com/go-logr/stdr)
|
||||
- **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
|
||||
- **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend)
|
||||
- **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr)
|
||||
|
||||
## FAQ
|
||||
|
||||
### Conceptual
|
||||
|
||||
#### Why structured logging?
|
||||
|
||||
- **Structured logs are more easily queryable**: Since you've got
|
||||
key-value pairs, it's much easier to query your structured logs for
|
||||
particular values by filtering on the contents of a particular key --
|
||||
think searching request logs for error codes, Kubernetes reconcilers for
|
||||
the name and namespace of the reconciled object, etc.
|
||||
|
||||
- **Structured logging makes it easier to have cross-referenceable logs**:
|
||||
Similarly to searchability, if you maintain conventions around your
|
||||
keys, it becomes easy to gather all log lines related to a particular
|
||||
concept.
|
||||
|
||||
- **Structured logs allow better dimensions of filtering**: if you have
|
||||
structure to your logs, you've got more precise control over how much
|
||||
information is logged -- you might choose in a particular configuration
|
||||
to log certain keys but not others, only log lines where a certain key
|
||||
matches a certain value, etc., instead of just having v-levels and names
|
||||
to key off of.
|
||||
|
||||
- **Structured logs better represent structured data**: sometimes, the
|
||||
data that you want to log is inherently structured (think tuple-link
|
||||
objects.) Structured logs allow you to preserve that structure when
|
||||
outputting.
|
||||
|
||||
#### Why V-levels?
|
||||
|
||||
**V-levels give operators an easy way to control the chattiness of log
|
||||
operations**. V-levels provide a way for a given package to distinguish
|
||||
the relative importance or verbosity of a given log message. Then, if
|
||||
a particular logger or package is logging too many messages, the user
|
||||
of the package can simply change the v-levels for that library.
|
||||
|
||||
#### Why not named levels, like Info/Warning/Error?
|
||||
|
||||
Read [Dave Cheney's post][warning-makes-no-sense]. Then read [Differences
|
||||
from Dave's ideas](#differences-from-daves-ideas).
|
||||
|
||||
#### Why not allow format strings, too?
|
||||
|
||||
**Format strings negate many of the benefits of structured logs**:
|
||||
|
||||
- They're not easily searchable without resorting to fuzzy searching,
|
||||
regular expressions, etc.
|
||||
|
||||
- They don't store structured data well, since contents are flattened into
|
||||
a string.
|
||||
|
||||
- They're not cross-referenceable.
|
||||
|
||||
- They don't compress easily, since the message is not constant.
|
||||
|
||||
(Unless you turn positional parameters into key-value pairs with numerical
|
||||
keys, at which point you've gotten key-value logging with meaningless
|
||||
keys.)
|
||||
|
||||
### Practical
|
||||
|
||||
#### Why key-value pairs, and not a map?
|
||||
|
||||
Key-value pairs are *much* easier to optimize, especially around
|
||||
allocations. Zap (a structured logger that inspired logr's interface) has
|
||||
[performance measurements](https://github.com/uber-go/zap#performance)
|
||||
that show this quite nicely.
|
||||
|
||||
While the interface ends up being a little less obvious, you get
|
||||
potentially better performance, plus avoid making users type
|
||||
`map[string]string{}` every time they want to log.
|
||||
|
||||
#### What if my V-levels differ between libraries?
|
||||
|
||||
That's fine. Control your V-levels on a per-logger basis, and use the
|
||||
`WithName` method to pass different loggers to different libraries.
|
||||
|
||||
Generally, you should take care to ensure that you have relatively
|
||||
consistent V-levels within a given logger, however, as this makes deciding
|
||||
on what verbosity of logs to request easier.
|
||||
|
||||
#### But I really want to use a format string!
|
||||
|
||||
That's not actually a question. Assuming your question is "how do
|
||||
I convert my mental model of logging with format strings to logging with
|
||||
constant messages":
|
||||
|
||||
1. Figure out what the error actually is, as you'd write in a TL;DR style,
|
||||
and use that as a message.
|
||||
|
||||
2. For every place you'd write a format specifier, look to the word before
|
||||
it, and add that as a key value pair.
|
||||
|
||||
For instance, consider the following examples (all taken from spots in the
|
||||
Kubernetes codebase):
|
||||
|
||||
- `klog.V(4).Infof("Client is returning errors: code %v, error %v",
|
||||
responseCode, err)` becomes `logger.Error(err, "client returned an
|
||||
error", "code", responseCode)`
|
||||
|
||||
- `klog.V(4).Infof("Got a Retry-After %ds response for attempt %d to %v",
|
||||
seconds, retries, url)` becomes `logger.V(4).Info("got a retry-after
|
||||
response when requesting url", "attempt", retries, "after
|
||||
seconds", seconds, "url", url)`
|
||||
|
||||
If you *really* must use a format string, use it in a key's value, and
|
||||
call `fmt.Sprintf` yourself. For instance: `log.Printf("unable to
|
||||
reflect over type %T")` becomes `logger.Info("unable to reflect over
|
||||
type", "type", fmt.Sprintf("%T"))`. In general though, the cases where
|
||||
this is necessary should be few and far between.
|
||||
|
||||
#### How do I choose my V-levels?
|
||||
|
||||
This is basically the only hard constraint: increase V-levels to denote
|
||||
more verbose or more debug-y logs.
|
||||
|
||||
Otherwise, you can start out with `0` as "you always want to see this",
|
||||
`1` as "common logging that you might *possibly* want to turn off", and
|
||||
`10` as "I would like to performance-test your log collection stack."
|
||||
|
||||
Then gradually choose levels in between as you need them, working your way
|
||||
down from 10 (for debug and trace style logs) and up from 1 (for chattier
|
||||
info-type logs.)
|
||||
|
||||
#### How do I choose my keys?
|
||||
|
||||
Keys are fairly flexible, and can hold more or less any string
|
||||
value. For best compatibility with implementations and consistency
|
||||
with existing code in other projects, there are a few conventions you
|
||||
should consider.
|
||||
|
||||
- Make your keys human-readable.
|
||||
- Constant keys are generally a good idea.
|
||||
- Be consistent across your codebase.
|
||||
- Keys should naturally match parts of the message string.
|
||||
- Use lower case for simple keys and
|
||||
[lowerCamelCase](https://en.wiktionary.org/wiki/lowerCamelCase) for
|
||||
more complex ones. Kubernetes is one example of a project that has
|
||||
[adopted that
|
||||
convention](https://github.com/kubernetes/community/blob/HEAD/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments).
|
||||
|
||||
While key names are mostly unrestricted (and spaces are acceptable),
|
||||
it's generally a good idea to stick to printable ascii characters, or at
|
||||
least match the general character set of your log lines.
|
||||
|
||||
#### Why should keys be constant values?
|
||||
|
||||
The point of structured logging is to make later log processing easier. Your
|
||||
keys are, effectively, the schema of each log message. If you use different
|
||||
keys across instances of the same log line, you will make your structured logs
|
||||
much harder to use. `Sprintf()` is for values, not for keys!
|
||||
|
||||
#### Why is this not a pure interface?
|
||||
|
||||
The Logger type is implemented as a struct in order to allow the Go compiler to
|
||||
optimize things like high-V `Info` logs that are not triggered. Not all of
|
||||
these implementations are implemented yet, but this structure was suggested as
|
||||
a way to ensure they *can* be implemented. All of the real work is behind the
|
||||
`LogSink` interface.
|
||||
|
||||
[warning-makes-no-sense]: http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
54
vendor/github.com/go-logr/logr/discard.go
generated
vendored
54
vendor/github.com/go-logr/logr/discard.go
generated
vendored
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 The logr Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package logr
|
||||
|
||||
// Discard returns a Logger that discards all messages logged to it. It can be
|
||||
// used whenever the caller is not interested in the logs. Logger instances
|
||||
// produced by this function always compare as equal.
|
||||
func Discard() Logger {
|
||||
return Logger{
|
||||
level: 0,
|
||||
sink: discardLogSink{},
|
||||
}
|
||||
}
|
||||
|
||||
// discardLogSink is a LogSink that discards all messages.
|
||||
type discardLogSink struct{}
|
||||
|
||||
// Verify that it actually implements the interface
|
||||
var _ LogSink = discardLogSink{}
|
||||
|
||||
func (l discardLogSink) Init(RuntimeInfo) {
|
||||
}
|
||||
|
||||
func (l discardLogSink) Enabled(int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (l discardLogSink) Info(int, string, ...interface{}) {
|
||||
}
|
||||
|
||||
func (l discardLogSink) Error(error, string, ...interface{}) {
|
||||
}
|
||||
|
||||
func (l discardLogSink) WithValues(...interface{}) LogSink {
|
||||
return l
|
||||
}
|
||||
|
||||
func (l discardLogSink) WithName(string) LogSink {
|
||||
return l
|
||||
}
|
411
vendor/github.com/go-logr/logr/funcr/funcr.go
generated
vendored
411
vendor/github.com/go-logr/logr/funcr/funcr.go
generated
vendored
@@ -1,411 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The logr Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package funcr implements formatting of structured log messages and
|
||||
// optionally captures the call site. This will not call String or
|
||||
// Error methods on values.
|
||||
//
|
||||
// The simplest way to use it is via its implementation of a
|
||||
// github.com/go-logr/logr.LogSink with output through an arbitrary
|
||||
// "write" function. Alternatively, funcr can also be embedded inside
|
||||
// a custom LogSink implementation. This is useful when the LogSink
|
||||
// needs to implement additional methods.
|
||||
package funcr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
)
|
||||
|
||||
// New returns a logr.Logger which is implemented by an arbitrary function.
|
||||
func New(fn func(prefix, args string), opts Options) logr.Logger {
|
||||
return logr.New(newSink(fn, opts))
|
||||
}
|
||||
|
||||
// Underlier exposes access to the underlying logging function. Since
|
||||
// callers only have a logr.Logger, they have to know which
|
||||
// implementation is in use, so this interface is less of an
|
||||
// abstraction and more of a way to test type conversion.
|
||||
type Underlier interface {
|
||||
GetUnderlying() func(prefix, args string)
|
||||
}
|
||||
|
||||
func newSink(fn func(prefix, args string), opts Options) logr.LogSink {
|
||||
l := &fnlogger{
|
||||
Formatter: NewFormatter(opts),
|
||||
write: fn,
|
||||
}
|
||||
// For skipping fnlogger.Info and fnlogger.Error.
|
||||
l.Formatter.AddCallDepth(1)
|
||||
return l
|
||||
}
|
||||
|
||||
// Options carries parameters which influence the way logs are generated.
|
||||
type Options struct {
|
||||
// LogCaller tells funcr to add a "caller" key to some or all log lines.
|
||||
// This has some overhead, so some users might not want it.
|
||||
LogCaller MessageClass
|
||||
|
||||
// LogTimestamp tells funcr to add a "ts" key to log lines. This has some
|
||||
// overhead, so some users might not want it.
|
||||
LogTimestamp bool
|
||||
|
||||
// Verbosity tells funcr which V logs to be write. Higher values enable
|
||||
// more logs.
|
||||
Verbosity int
|
||||
}
|
||||
|
||||
// MessageClass indicates which category or categories of messages to consider.
|
||||
type MessageClass int
|
||||
|
||||
const (
|
||||
// None ignores all message classes.
|
||||
None MessageClass = iota
|
||||
// All considers all message classes.
|
||||
All
|
||||
// Info only considers info messages.
|
||||
Info
|
||||
// Error only considers error messages.
|
||||
Error
|
||||
)
|
||||
|
||||
const timestampFmt = "2006-01-02 15:04:05.000000"
|
||||
|
||||
// fnlogger inherits some of its LogSink implementation from Formatter
|
||||
// and just needs to add some glue code.
|
||||
type fnlogger struct {
|
||||
Formatter
|
||||
write func(prefix, args string)
|
||||
}
|
||||
|
||||
func (l fnlogger) WithName(name string) logr.LogSink {
|
||||
l.Formatter.AddName(name)
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l fnlogger) WithValues(kvList ...interface{}) logr.LogSink {
|
||||
l.Formatter.AddValues(kvList)
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l fnlogger) WithCallDepth(depth int) logr.LogSink {
|
||||
l.Formatter.AddCallDepth(depth)
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l fnlogger) Info(level int, msg string, kvList ...interface{}) {
|
||||
prefix, args := l.FormatInfo(level, msg, kvList)
|
||||
l.write(prefix, args)
|
||||
}
|
||||
|
||||
func (l fnlogger) Error(err error, msg string, kvList ...interface{}) {
|
||||
prefix, args := l.FormatError(err, msg, kvList)
|
||||
l.write(prefix, args)
|
||||
}
|
||||
|
||||
func (l fnlogger) GetUnderlying() func(prefix, args string) {
|
||||
return l.write
|
||||
}
|
||||
|
||||
// Assert conformance to the interfaces.
|
||||
var _ logr.LogSink = &fnlogger{}
|
||||
var _ logr.CallDepthLogSink = &fnlogger{}
|
||||
var _ Underlier = &fnlogger{}
|
||||
|
||||
func flatten(kvList ...interface{}) string {
|
||||
if len(kvList)%2 != 0 {
|
||||
kvList = append(kvList, "<no-value>")
|
||||
}
|
||||
// Empirically bytes.Buffer is faster than strings.Builder for this.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
for i := 0; i < len(kvList); i += 2 {
|
||||
k, ok := kvList[i].(string)
|
||||
if !ok {
|
||||
k = fmt.Sprintf("<non-string-key-%d>", i/2)
|
||||
}
|
||||
v := kvList[i+1]
|
||||
|
||||
if i > 0 {
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
buf.WriteRune('"')
|
||||
buf.WriteString(k)
|
||||
buf.WriteRune('"')
|
||||
buf.WriteRune('=')
|
||||
buf.WriteString(pretty(v))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func pretty(value interface{}) string {
|
||||
return prettyWithFlags(value, 0)
|
||||
}
|
||||
|
||||
const (
|
||||
flagRawString = 0x1
|
||||
)
|
||||
|
||||
// TODO: This is not fast. Most of the overhead goes here.
|
||||
func prettyWithFlags(value interface{}, flags uint32) string {
|
||||
// Handling the most common types without reflect is a small perf win.
|
||||
switch v := value.(type) {
|
||||
case bool:
|
||||
return strconv.FormatBool(v)
|
||||
case string:
|
||||
if flags&flagRawString > 0 {
|
||||
return v
|
||||
}
|
||||
// This is empirically faster than strings.Builder.
|
||||
return `"` + v + `"`
|
||||
case int:
|
||||
return strconv.FormatInt(int64(v), 10)
|
||||
case int8:
|
||||
return strconv.FormatInt(int64(v), 10)
|
||||
case int16:
|
||||
return strconv.FormatInt(int64(v), 10)
|
||||
case int32:
|
||||
return strconv.FormatInt(int64(v), 10)
|
||||
case int64:
|
||||
return strconv.FormatInt(int64(v), 10)
|
||||
case uint:
|
||||
return strconv.FormatUint(uint64(v), 10)
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(v), 10)
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(v), 10)
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(v), 10)
|
||||
case uint64:
|
||||
return strconv.FormatUint(v, 10)
|
||||
case uintptr:
|
||||
return strconv.FormatUint(uint64(v), 10)
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(v), 'f', -1, 32)
|
||||
case float64:
|
||||
return strconv.FormatFloat(v, 'f', -1, 64)
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 256))
|
||||
t := reflect.TypeOf(value)
|
||||
if t == nil {
|
||||
return "null"
|
||||
}
|
||||
v := reflect.ValueOf(value)
|
||||
switch t.Kind() {
|
||||
case reflect.Bool:
|
||||
return strconv.FormatBool(v.Bool())
|
||||
case reflect.String:
|
||||
if flags&flagRawString > 0 {
|
||||
return v.String()
|
||||
}
|
||||
// This is empirically faster than strings.Builder.
|
||||
return `"` + v.String() + `"`
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return strconv.FormatInt(int64(v.Int()), 10)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return strconv.FormatUint(uint64(v.Uint()), 10)
|
||||
case reflect.Float32:
|
||||
return strconv.FormatFloat(float64(v.Float()), 'f', -1, 32)
|
||||
case reflect.Float64:
|
||||
return strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||
case reflect.Struct:
|
||||
buf.WriteRune('{')
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
f := t.Field(i)
|
||||
if f.PkgPath != "" {
|
||||
// reflect says this field is only defined for non-exported fields.
|
||||
continue
|
||||
}
|
||||
if i > 0 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
buf.WriteRune('"')
|
||||
name := f.Name
|
||||
if tag, found := f.Tag.Lookup("json"); found {
|
||||
if comma := strings.Index(tag, ","); comma != -1 {
|
||||
name = tag[:comma]
|
||||
} else {
|
||||
name = tag
|
||||
}
|
||||
}
|
||||
buf.WriteString(name)
|
||||
buf.WriteRune('"')
|
||||
buf.WriteRune(':')
|
||||
buf.WriteString(pretty(v.Field(i).Interface()))
|
||||
}
|
||||
buf.WriteRune('}')
|
||||
return buf.String()
|
||||
case reflect.Slice, reflect.Array:
|
||||
buf.WriteRune('[')
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
if i > 0 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
e := v.Index(i)
|
||||
buf.WriteString(pretty(e.Interface()))
|
||||
}
|
||||
buf.WriteRune(']')
|
||||
return buf.String()
|
||||
case reflect.Map:
|
||||
buf.WriteRune('{')
|
||||
// This does not sort the map keys, for best perf.
|
||||
it := v.MapRange()
|
||||
i := 0
|
||||
for it.Next() {
|
||||
if i > 0 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
// JSON only does string keys.
|
||||
buf.WriteRune('"')
|
||||
buf.WriteString(prettyWithFlags(it.Key().Interface(), flagRawString))
|
||||
buf.WriteRune('"')
|
||||
buf.WriteRune(':')
|
||||
buf.WriteString(pretty(it.Value().Interface()))
|
||||
i++
|
||||
}
|
||||
buf.WriteRune('}')
|
||||
return buf.String()
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return pretty(v.Elem().Interface())
|
||||
}
|
||||
return fmt.Sprintf(`"<unhandled-%s>"`, t.Kind().String())
|
||||
}
|
||||
|
||||
type callerID struct {
|
||||
File string `json:"file"`
|
||||
Line int `json:"line"`
|
||||
}
|
||||
|
||||
// NewFormatter constructs a Formatter.
|
||||
func NewFormatter(opts Options) Formatter {
|
||||
f := Formatter{
|
||||
prefix: "",
|
||||
values: nil,
|
||||
depth: 0,
|
||||
logCaller: opts.LogCaller,
|
||||
logTimestamp: opts.LogTimestamp,
|
||||
verbosity: opts.Verbosity,
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// Formatter is an opaque struct which can be embedded in a LogSink
|
||||
// implementation. It should be constructed with NewFormatter. Some of
|
||||
// its methods directly implement logr.LogSink.
|
||||
type Formatter struct {
|
||||
prefix string
|
||||
values []interface{}
|
||||
depth int
|
||||
logCaller MessageClass
|
||||
logTimestamp bool
|
||||
verbosity int
|
||||
}
|
||||
|
||||
func (f Formatter) caller() callerID {
|
||||
// +1 for this frame, +1 for Info/Error.
|
||||
_, file, line, ok := runtime.Caller(f.depth + 2)
|
||||
if !ok {
|
||||
return callerID{"<unknown>", 0}
|
||||
}
|
||||
return callerID{filepath.Base(file), line}
|
||||
}
|
||||
|
||||
// Init configures this Formatter from runtime info, such as the call depth
|
||||
// imposed by logr itself.
|
||||
// Note that this receiver is a pointer, so depth can be saved.
|
||||
func (f *Formatter) Init(info logr.RuntimeInfo) {
|
||||
f.depth += info.CallDepth
|
||||
}
|
||||
|
||||
// Enabled checks whether an info message at the given level should be logged.
|
||||
func (f Formatter) Enabled(level int) bool {
|
||||
return level <= f.verbosity
|
||||
}
|
||||
|
||||
// GetDepth returns the current depth of this Formatter. This is useful for
|
||||
// implementations which do their own caller attribution.
|
||||
func (f Formatter) GetDepth() int {
|
||||
return f.depth
|
||||
}
|
||||
|
||||
// FormatInfo flattens an Info log message into strings.
|
||||
// The prefix will be empty when no names were set.
|
||||
func (f Formatter) FormatInfo(level int, msg string, kvList []interface{}) (prefix, argsStr string) {
|
||||
args := make([]interface{}, 0, 64) // using a constant here impacts perf
|
||||
if f.logTimestamp {
|
||||
args = append(args, "ts", time.Now().Format(timestampFmt))
|
||||
}
|
||||
if f.logCaller == All || f.logCaller == Info {
|
||||
args = append(args, "caller", f.caller())
|
||||
}
|
||||
args = append(args, "level", level, "msg", msg)
|
||||
args = append(args, f.values...)
|
||||
args = append(args, kvList...)
|
||||
return f.prefix, flatten(args...)
|
||||
}
|
||||
|
||||
// FormatError flattens an Error log message into strings.
|
||||
// The prefix will be empty when no names were set.
|
||||
func (f Formatter) FormatError(err error, msg string, kvList []interface{}) (prefix, argsStr string) {
|
||||
args := make([]interface{}, 0, 64) // using a constant here impacts perf
|
||||
if f.logTimestamp {
|
||||
args = append(args, "ts", time.Now().Format(timestampFmt))
|
||||
}
|
||||
if f.logCaller == All || f.logCaller == Error {
|
||||
args = append(args, "caller", f.caller())
|
||||
}
|
||||
args = append(args, "msg", msg)
|
||||
var loggableErr interface{}
|
||||
if err != nil {
|
||||
loggableErr = err.Error()
|
||||
}
|
||||
args = append(args, "error", loggableErr)
|
||||
args = append(args, f.values...)
|
||||
args = append(args, kvList...)
|
||||
return f.prefix, flatten(args...)
|
||||
}
|
||||
|
||||
// AddName appends the specified name. funcr uses '/' characters to separate
|
||||
// name elements. Callers should not pass '/' in the provided name string, but
|
||||
// this library does not actually enforce that.
|
||||
func (f *Formatter) AddName(name string) {
|
||||
if len(f.prefix) > 0 {
|
||||
f.prefix += "/"
|
||||
}
|
||||
f.prefix += name
|
||||
}
|
||||
|
||||
// AddValues adds key-value pairs to the set of saved values to be logged with
|
||||
// each log line.
|
||||
func (f *Formatter) AddValues(kvList []interface{}) {
|
||||
// Three slice args forces a copy.
|
||||
n := len(f.values)
|
||||
f.values = append(f.values[:n:n], kvList...)
|
||||
}
|
||||
|
||||
// AddCallDepth increases the number of stack-frames to skip when attributing
|
||||
// the log line to a file and line.
|
||||
func (f *Formatter) AddCallDepth(depth int) {
|
||||
f.depth += depth
|
||||
}
|
479
vendor/github.com/go-logr/logr/logr.go
generated
vendored
479
vendor/github.com/go-logr/logr/logr.go
generated
vendored
@@ -1,479 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 The logr Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This design derives from Dave Cheney's blog:
|
||||
// http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
||||
|
||||
// Package logr defines a general-purpose logging API and abstract interfaces
|
||||
// to back that API. Packages in the Go ecosystem can depend on this package,
|
||||
// while callers can implement logging with whatever backend is appropriate.
|
||||
//
|
||||
// # Usage
|
||||
//
|
||||
// Logging is done using a Logger instance. Logger is a concrete type with
|
||||
// methods, which defers the actual logging to a LogSink interface. The main
|
||||
// methods of Logger are Info() and Error(). Arguments to Info() and Error()
|
||||
// are key/value pairs rather than printf-style formatted strings, emphasizing
|
||||
// "structured logging".
|
||||
//
|
||||
// With Go's standard log package, we might write:
|
||||
// log.Printf("setting target value %s", targetValue)
|
||||
//
|
||||
// With logr's structured logging, we'd write:
|
||||
// logger.Info("setting target", "value", targetValue)
|
||||
//
|
||||
// Errors are much the same. Instead of:
|
||||
// log.Printf("failed to open the pod bay door for user %s: %v", user, err)
|
||||
//
|
||||
// We'd write:
|
||||
// logger.Error(err, "failed to open the pod bay door", "user", user)
|
||||
//
|
||||
// Info() and Error() are very similar, but they are separate methods so that
|
||||
// LogSink implementations can choose to do things like attach additional
|
||||
// information (such as stack traces) on calls to Error().
|
||||
//
|
||||
// # Verbosity
|
||||
//
|
||||
// Often we want to log information only when the application in "verbose
|
||||
// mode". To write log lines that are more verbose, Logger has a V() method.
|
||||
// The higher the V-level of a log line, the less critical it is considered.
|
||||
// Log-lines with V-levels that are not enabled (as per the LogSink) will not
|
||||
// be written. Level V(0) is the default, and logger.V(0).Info() has the same
|
||||
// meaning as logger.Info(). Negative V-levels have the same meaning as V(0).
|
||||
//
|
||||
// Where we might have written:
|
||||
// if flVerbose >= 2 {
|
||||
// log.Printf("an unusual thing happened")
|
||||
// }
|
||||
//
|
||||
// We can write:
|
||||
// logger.V(2).Info("an unusual thing happened")
|
||||
//
|
||||
// # Logger Names
|
||||
//
|
||||
// Logger instances can have name strings so that all messages logged through
|
||||
// that instance have additional context. For example, you might want to add
|
||||
// a subsystem name:
|
||||
//
|
||||
// logger.WithName("compactor").Info("started", "time", time.Now())
|
||||
//
|
||||
// The WithName() method returns a new Logger, which can be passed to
|
||||
// constructors or other functions for further use. Repeated use of WithName()
|
||||
// will accumulate name "segments". These name segments will be joined in some
|
||||
// way by the LogSink implementation. It is strongly recommended that name
|
||||
// segments contain simple identifiers (letters, digits, and hyphen), and do
|
||||
// not contain characters that could muddle the log output or confuse the
|
||||
// joining operation (e.g. whitespace, commas, periods, slashes, brackets,
|
||||
// quotes, etc).
|
||||
//
|
||||
// # Saved Values
|
||||
//
|
||||
// Logger instances can store any number of key/value pairs, which will be
|
||||
// logged alongside all messages logged through that instance. For example,
|
||||
// you might want to create a Logger instance per managed object:
|
||||
//
|
||||
// With the standard log package, we might write:
|
||||
// log.Printf("decided to set field foo to value %q for object %s/%s",
|
||||
// targetValue, object.Namespace, object.Name)
|
||||
//
|
||||
// With logr we'd write:
|
||||
// // Elsewhere: set up the logger to log the object name.
|
||||
// obj.logger = mainLogger.WithValues(
|
||||
// "name", obj.name, "namespace", obj.namespace)
|
||||
//
|
||||
// // later on...
|
||||
// obj.logger.Info("setting foo", "value", targetValue)
|
||||
//
|
||||
// # Best Practices
|
||||
//
|
||||
// Logger has very few hard rules, with the goal that LogSink implementations
|
||||
// might have a lot of freedom to differentiate. There are, however, some
|
||||
// things to consider.
|
||||
//
|
||||
// The log message consists of a constant message attached to the log line.
|
||||
// This should generally be a simple description of what's occurring, and should
|
||||
// never be a format string. Variable information can then be attached using
|
||||
// named values.
|
||||
//
|
||||
// Keys are arbitrary strings, but should generally be constant values. Values
|
||||
// may be any Go value, but how the value is formatted is determined by the
|
||||
// LogSink implementation.
|
||||
//
|
||||
// # Key Naming Conventions
|
||||
//
|
||||
// Keys are not strictly required to conform to any specification or regex, but
|
||||
// it is recommended that they:
|
||||
// * be human-readable and meaningful (not auto-generated or simple ordinals)
|
||||
// * be constant (not dependent on input data)
|
||||
// * contain only printable characters
|
||||
// * not contain whitespace or punctuation
|
||||
// * use lower case for simple keys and lowerCamelCase for more complex ones
|
||||
//
|
||||
// These guidelines help ensure that log data is processed properly regardless
|
||||
// of the log implementation. For example, log implementations will try to
|
||||
// output JSON data or will store data for later database (e.g. SQL) queries.
|
||||
//
|
||||
// While users are generally free to use key names of their choice, it's
|
||||
// generally best to avoid using the following keys, as they're frequently used
|
||||
// by implementations:
|
||||
//
|
||||
// * "caller": the calling information (file/line) of a particular log line.
|
||||
// * "error": the underlying error value in the `Error` method.
|
||||
// * "level": the log level.
|
||||
// * "logger": the name of the associated logger.
|
||||
// * "msg": the log message.
|
||||
// * "stacktrace": the stack trace associated with a particular log line or
|
||||
// error (often from the `Error` message).
|
||||
// * "ts": the timestamp for a log line.
|
||||
//
|
||||
// Implementations are encouraged to make use of these keys to represent the
|
||||
// above concepts, when necessary (for example, in a pure-JSON output form, it
|
||||
// would be necessary to represent at least message and timestamp as ordinary
|
||||
// named values).
|
||||
//
|
||||
// # Break Glass
|
||||
//
|
||||
// Implementations may choose to give callers access to the underlying
|
||||
// logging implementation. The recommended pattern for this is:
|
||||
// // Underlier exposes access to the underlying logging implementation.
|
||||
// // Since callers only have a logr.Logger, they have to know which
|
||||
// // implementation is in use, so this interface is less of an abstraction
|
||||
// // and more of way to test type conversion.
|
||||
// type Underlier interface {
|
||||
// GetUnderlying() <underlying-type>
|
||||
// }
|
||||
//
|
||||
// Logger grants access to the sink to enable type assertions like this:
|
||||
// func DoSomethingWithImpl(log logr.Logger) {
|
||||
// if underlier, ok := log.GetSink()(impl.Underlier) {
|
||||
// implLogger := underlier.GetUnderlying()
|
||||
// ...
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Custom `With*` functions can be implemented by copying the complete
|
||||
// Logger struct and replacing the sink in the copy:
|
||||
// // WithFooBar changes the foobar parameter in the log sink and returns a
|
||||
// // new logger with that modified sink. It does nothing for loggers where
|
||||
// // the sink doesn't support that parameter.
|
||||
// func WithFoobar(log logr.Logger, foobar int) logr.Logger {
|
||||
// if foobarLogSink, ok := log.GetSink()(FoobarSink); ok {
|
||||
// log = log.WithSink(foobarLogSink.WithFooBar(foobar))
|
||||
// }
|
||||
// return log
|
||||
// }
|
||||
//
|
||||
// Don't use New to construct a new Logger with a LogSink retrieved from an
|
||||
// existing Logger. Source code attribution might not work correctly and
|
||||
// unexported fields in Logger get lost.
|
||||
//
|
||||
// Beware that the same LogSink instance may be shared by different logger
|
||||
// instances. Calling functions that modify the LogSink will affect all of
|
||||
// those.
|
||||
package logr
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// New returns a new Logger instance. This is primarily used by libraries
|
||||
// implementing LogSink, rather than end users.
|
||||
func New(sink LogSink) Logger {
|
||||
logger := Logger{}
|
||||
logger.setSink(sink)
|
||||
sink.Init(runtimeInfo)
|
||||
return logger
|
||||
}
|
||||
|
||||
// setSink stores the sink and updates any related fields. It mutates the
|
||||
// logger and thus is only safe to use for loggers that are not currently being
|
||||
// used concurrently.
|
||||
func (l *Logger) setSink(sink LogSink) {
|
||||
l.sink = sink
|
||||
}
|
||||
|
||||
// GetSink returns the stored sink.
|
||||
func (l Logger) GetSink() LogSink {
|
||||
return l.sink
|
||||
}
|
||||
|
||||
// WithSink returns a copy of the logger with the new sink.
|
||||
func (l Logger) WithSink(sink LogSink) Logger {
|
||||
l.setSink(sink)
|
||||
return l
|
||||
}
|
||||
|
||||
// Logger is an interface to an abstract logging implementation. This is a
|
||||
// concrete type for performance reasons, but all the real work is passed on to
|
||||
// a LogSink. Implementations of LogSink should provide their own constructors
|
||||
// that return Logger, not LogSink.
|
||||
//
|
||||
// The underlying sink can be accessed through GetSink and be modified through
|
||||
// WithSink. This enables the implementation of custom extensions (see "Break
|
||||
// Glass" in the package documentation). Normally the sink should be used only
|
||||
// indirectly.
|
||||
type Logger struct {
|
||||
sink LogSink
|
||||
level int
|
||||
}
|
||||
|
||||
// Enabled tests whether this Logger is enabled. For example, commandline
|
||||
// flags might be used to set the logging verbosity and disable some info logs.
|
||||
func (l Logger) Enabled() bool {
|
||||
return l.sink.Enabled(l.level)
|
||||
}
|
||||
|
||||
// Info logs a non-error message with the given key/value pairs as context.
|
||||
//
|
||||
// The msg argument should be used to add some constant description to the log
|
||||
// line. The key/value pairs can then be used to add additional variable
|
||||
// information. The key/value pairs must alternate string keys and arbitrary
|
||||
// values.
|
||||
func (l Logger) Info(msg string, keysAndValues ...interface{}) {
|
||||
if l.Enabled() {
|
||||
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||
withHelper.GetCallStackHelper()()
|
||||
}
|
||||
l.sink.Info(l.level, msg, keysAndValues...)
|
||||
}
|
||||
}
|
||||
|
||||
// Error logs an error, with the given message and key/value pairs as context.
|
||||
// It functions similarly to Info, but may have unique behavior, and should be
|
||||
// preferred for logging errors (see the package documentations for more
|
||||
// information).
|
||||
//
|
||||
// The msg argument should be used to add context to any underlying error,
|
||||
// while the err argument should be used to attach the actual error that
|
||||
// triggered this log line, if present.
|
||||
func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||
withHelper.GetCallStackHelper()()
|
||||
}
|
||||
l.sink.Error(err, msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// V returns a new Logger instance for a specific verbosity level, relative to
|
||||
// this Logger. In other words, V-levels are additive. A higher verbosity
|
||||
// level means a log message is less important. Negative V-levels are treated
|
||||
// as 0.
|
||||
func (l Logger) V(level int) Logger {
|
||||
if level < 0 {
|
||||
level = 0
|
||||
}
|
||||
l.level += level
|
||||
return l
|
||||
}
|
||||
|
||||
// WithValues returns a new Logger instance with additional key/value pairs.
|
||||
// See Info for documentation on how key/value pairs work.
|
||||
func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
|
||||
l.setSink(l.sink.WithValues(keysAndValues...))
|
||||
return l
|
||||
}
|
||||
|
||||
// WithName returns a new Logger instance with the specified name element added
|
||||
// to the Logger's name. Successive calls with WithName append additional
|
||||
// suffixes to the Logger's name. It's strongly recommended that name segments
|
||||
// contain only letters, digits, and hyphens (see the package documentation for
|
||||
// more information).
|
||||
func (l Logger) WithName(name string) Logger {
|
||||
l.setSink(l.sink.WithName(name))
|
||||
return l
|
||||
}
|
||||
|
||||
// WithCallDepth returns a Logger instance that offsets the call stack by the
|
||||
// specified number of frames when logging call site information, if possible.
|
||||
// This is useful for users who have helper functions between the "real" call
|
||||
// site and the actual calls to Logger methods. If depth is 0 the attribution
|
||||
// should be to the direct caller of this function. If depth is 1 the
|
||||
// attribution should skip 1 call frame, and so on. Successive calls to this
|
||||
// are additive.
|
||||
//
|
||||
// If the underlying log implementation supports a WithCallDepth(int) method,
|
||||
// it will be called and the result returned. If the implementation does not
|
||||
// support CallDepthLogSink, the original Logger will be returned.
|
||||
//
|
||||
// To skip one level, WithCallStackHelper() should be used instead of
|
||||
// WithCallDepth(1) because it works with implementions that support the
|
||||
// CallDepthLogSink and/or CallStackHelperLogSink interfaces.
|
||||
func (l Logger) WithCallDepth(depth int) Logger {
|
||||
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
|
||||
l.setSink(withCallDepth.WithCallDepth(depth))
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// WithCallStackHelper returns a new Logger instance that skips the direct
|
||||
// caller when logging call site information, if possible. This is useful for
|
||||
// users who have helper functions between the "real" call site and the actual
|
||||
// calls to Logger methods and want to support loggers which depend on marking
|
||||
// each individual helper function, like loggers based on testing.T.
|
||||
//
|
||||
// In addition to using that new logger instance, callers also must call the
|
||||
// returned function.
|
||||
//
|
||||
// If the underlying log implementation supports a WithCallDepth(int) method,
|
||||
// WithCallDepth(1) will be called to produce a new logger. If it supports a
|
||||
// WithCallStackHelper() method, that will be also called. If the
|
||||
// implementation does not support either of these, the original Logger will be
|
||||
// returned.
|
||||
func (l Logger) WithCallStackHelper() (func(), Logger) {
|
||||
var helper func()
|
||||
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
|
||||
l.setSink(withCallDepth.WithCallDepth(1))
|
||||
}
|
||||
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||
helper = withHelper.GetCallStackHelper()
|
||||
} else {
|
||||
helper = func() {}
|
||||
}
|
||||
return helper, l
|
||||
}
|
||||
|
||||
// contextKey is how we find Loggers in a context.Context.
|
||||
type contextKey struct{}
|
||||
|
||||
// FromContext returns a Logger from ctx or an error if no Logger is found.
|
||||
func FromContext(ctx context.Context) (Logger, error) {
|
||||
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return Logger{}, notFoundError{}
|
||||
}
|
||||
|
||||
// notFoundError exists to carry an IsNotFound method.
|
||||
type notFoundError struct{}
|
||||
|
||||
func (notFoundError) Error() string {
|
||||
return "no logr.Logger was present"
|
||||
}
|
||||
|
||||
func (notFoundError) IsNotFound() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// FromContextOrDiscard returns a Logger from ctx. If no Logger is found, this
|
||||
// returns a Logger that discards all log messages.
|
||||
func FromContextOrDiscard(ctx context.Context) Logger {
|
||||
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return Discard()
|
||||
}
|
||||
|
||||
// NewContext returns a new Context, derived from ctx, which carries the
|
||||
// provided Logger.
|
||||
func NewContext(ctx context.Context, logger Logger) context.Context {
|
||||
return context.WithValue(ctx, contextKey{}, logger)
|
||||
}
|
||||
|
||||
// RuntimeInfo holds information that the logr "core" library knows which
|
||||
// LogSinks might want to know.
|
||||
type RuntimeInfo struct {
|
||||
// CallDepth is the number of call frames the logr library adds between the
|
||||
// end-user and the LogSink. LogSink implementations which choose to print
|
||||
// the original logging site (e.g. file & line) should climb this many
|
||||
// additional frames to find it.
|
||||
CallDepth int
|
||||
}
|
||||
|
||||
// runtimeInfo is a static global. It must not be changed at run time.
|
||||
var runtimeInfo = RuntimeInfo{
|
||||
CallDepth: 1,
|
||||
}
|
||||
|
||||
// LogSink represents a logging implementation. End-users will generally not
|
||||
// interact with this type.
|
||||
type LogSink interface {
|
||||
// Init receives optional information about the logr library for LogSink
|
||||
// implementations that need it.
|
||||
Init(info RuntimeInfo)
|
||||
|
||||
// Enabled tests whether this LogSink is enabled at the specified V-level.
|
||||
// For example, commandline flags might be used to set the logging
|
||||
// verbosity and disable some info logs.
|
||||
Enabled(level int) bool
|
||||
|
||||
// Info logs a non-error message with the given key/value pairs as context.
|
||||
// The level argument is provided for optional logging. This method will
|
||||
// only be called when Enabled(level) is true. See Logger.Info for more
|
||||
// details.
|
||||
Info(level int, msg string, keysAndValues ...interface{})
|
||||
|
||||
// Error logs an error, with the given message and key/value pairs as
|
||||
// context. See Logger.Error for more details.
|
||||
Error(err error, msg string, keysAndValues ...interface{})
|
||||
|
||||
// WithValues returns a new LogSink with additional key/value pairs. See
|
||||
// Logger.WithValues for more details.
|
||||
WithValues(keysAndValues ...interface{}) LogSink
|
||||
|
||||
// WithName returns a new LogSink with the specified name appended. See
|
||||
// Logger.WithName for more details.
|
||||
WithName(name string) LogSink
|
||||
}
|
||||
|
||||
// CallDepthLogSink represents a Logger that knows how to climb the call stack
|
||||
// to identify the original call site and can offset the depth by a specified
|
||||
// number of frames. This is useful for users who have helper functions
|
||||
// between the "real" call site and the actual calls to Logger methods.
|
||||
// Implementations that log information about the call site (such as file,
|
||||
// function, or line) would otherwise log information about the intermediate
|
||||
// helper functions.
|
||||
//
|
||||
// This is an optional interface and implementations are not required to
|
||||
// support it.
|
||||
type CallDepthLogSink interface {
|
||||
// WithCallDepth returns a LogSink that will offset the call
|
||||
// stack by the specified number of frames when logging call
|
||||
// site information.
|
||||
//
|
||||
// If depth is 0, the LogSink should skip exactly the number
|
||||
// of call frames defined in RuntimeInfo.CallDepth when Info
|
||||
// or Error are called, i.e. the attribution should be to the
|
||||
// direct caller of Logger.Info or Logger.Error.
|
||||
//
|
||||
// If depth is 1 the attribution should skip 1 call frame, and so on.
|
||||
// Successive calls to this are additive.
|
||||
WithCallDepth(depth int) LogSink
|
||||
}
|
||||
|
||||
// CallStackHelperLogSink represents a Logger that knows how to climb
|
||||
// the call stack to identify the original call site and can skip
|
||||
// intermediate helper functions if they mark themselves as
|
||||
// helper. Go's testing package uses that approach.
|
||||
//
|
||||
// This is useful for users who have helper functions between the
|
||||
// "real" call site and the actual calls to Logger methods.
|
||||
// Implementations that log information about the call site (such as
|
||||
// file, function, or line) would otherwise log information about the
|
||||
// intermediate helper functions.
|
||||
//
|
||||
// This is an optional interface and implementations are not required
|
||||
// to support it. Implementations that choose to support this must not
|
||||
// simply implement it as WithCallDepth(1), because
|
||||
// Logger.WithCallStackHelper will call both methods if they are
|
||||
// present. This should only be implemented for LogSinks that actually
|
||||
// need it, as with testing.T.
|
||||
type CallStackHelperLogSink interface {
|
||||
// GetCallStackHelper returns a function that must be called
|
||||
// to mark the direct caller as helper function when logging
|
||||
// call site information.
|
||||
GetCallStackHelper() func()
|
||||
}
|
201
vendor/github.com/go-logr/stdr/LICENSE
generated
vendored
201
vendor/github.com/go-logr/stdr/LICENSE
generated
vendored
@@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
4
vendor/github.com/go-logr/stdr/README.md
generated
vendored
4
vendor/github.com/go-logr/stdr/README.md
generated
vendored
@@ -1,4 +0,0 @@
|
||||
# Minimal Go logging using logr and Go's standard library
|
||||
|
||||
This package implements the [logr interface](https://github.com/go-logr/logr)
|
||||
in terms of Go's standard log package(https://godoc.org/std/log).
|
170
vendor/github.com/go-logr/stdr/stdr.go
generated
vendored
170
vendor/github.com/go-logr/stdr/stdr.go
generated
vendored
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 The logr Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package stdr implements github.com/go-logr/logr.Logger in terms of
|
||||
// Go's standard log package.
|
||||
package stdr
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/go-logr/logr/funcr"
|
||||
)
|
||||
|
||||
// The global verbosity level. See SetVerbosity().
|
||||
var globalVerbosity int
|
||||
|
||||
// SetVerbosity sets the global level against which all info logs will be
|
||||
// compared. If this is greater than or equal to the "V" of the logger, the
|
||||
// message will be logged. A higher value here means more logs will be written.
|
||||
// The previous verbosity value is returned. This is not concurrent-safe -
|
||||
// callers must be sure to call it from only one goroutine.
|
||||
func SetVerbosity(v int) int {
|
||||
old := globalVerbosity
|
||||
globalVerbosity = v
|
||||
return old
|
||||
}
|
||||
|
||||
// New returns a logr.Logger which is implemented by Go's standard log package,
|
||||
// or something like it. If std is nil, this will use a default logger
|
||||
// instead.
|
||||
//
|
||||
// Example: stdr.New(log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile)))
|
||||
func New(std StdLogger) logr.Logger {
|
||||
return NewWithOptions(std, Options{})
|
||||
}
|
||||
|
||||
// NewWithOptions returns a logr.Logger which is implemented by Go's standard
|
||||
// log package, or something like it. See New for details.
|
||||
func NewWithOptions(std StdLogger, opts Options) logr.Logger {
|
||||
if std == nil {
|
||||
// Go's log.Default() is only available in 1.16 and higher.
|
||||
std = log.New(os.Stderr, "", log.LstdFlags)
|
||||
}
|
||||
|
||||
if opts.Depth < 0 {
|
||||
opts.Depth = 0
|
||||
}
|
||||
|
||||
fopts := funcr.Options{
|
||||
LogCaller: funcr.MessageClass(opts.LogCaller),
|
||||
}
|
||||
|
||||
sl := &logger{
|
||||
Formatter: funcr.NewFormatter(fopts),
|
||||
std: std,
|
||||
}
|
||||
|
||||
// For skipping our own logger.Info/Error.
|
||||
sl.Formatter.AddCallDepth(1 + opts.Depth)
|
||||
|
||||
return logr.New(sl)
|
||||
}
|
||||
|
||||
// Options carries parameters which influence the way logs are generated.
|
||||
type Options struct {
|
||||
// Depth biases the assumed number of call frames to the "true" caller.
|
||||
// This is useful when the calling code calls a function which then calls
|
||||
// stdr (e.g. a logging shim to another API). Values less than zero will
|
||||
// be treated as zero.
|
||||
Depth int
|
||||
|
||||
// LogCaller tells stdr to add a "caller" key to some or all log lines.
|
||||
// Go's log package has options to log this natively, too.
|
||||
LogCaller MessageClass
|
||||
|
||||
// TODO: add an option to log the date/time
|
||||
}
|
||||
|
||||
// MessageClass indicates which category or categories of messages to consider.
|
||||
type MessageClass int
|
||||
|
||||
const (
|
||||
// None ignores all message classes.
|
||||
None MessageClass = iota
|
||||
// All considers all message classes.
|
||||
All
|
||||
// Info only considers info messages.
|
||||
Info
|
||||
// Error only considers error messages.
|
||||
Error
|
||||
)
|
||||
|
||||
// StdLogger is the subset of the Go stdlib log.Logger API that is needed for
|
||||
// this adapter.
|
||||
type StdLogger interface {
|
||||
// Output is the same as log.Output and log.Logger.Output.
|
||||
Output(calldepth int, logline string) error
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
funcr.Formatter
|
||||
std StdLogger
|
||||
}
|
||||
|
||||
var _ logr.LogSink = &logger{}
|
||||
var _ logr.CallDepthLogSink = &logger{}
|
||||
|
||||
func (l logger) Enabled(level int) bool {
|
||||
return globalVerbosity >= level
|
||||
}
|
||||
|
||||
func (l logger) Info(level int, msg string, kvList ...interface{}) {
|
||||
prefix, args := l.FormatInfo(level, msg, kvList)
|
||||
if prefix != "" {
|
||||
args = prefix + ": " + args
|
||||
}
|
||||
_ = l.std.Output(l.Formatter.GetDepth()+1, args)
|
||||
}
|
||||
|
||||
func (l logger) Error(err error, msg string, kvList ...interface{}) {
|
||||
prefix, args := l.FormatError(err, msg, kvList)
|
||||
if prefix != "" {
|
||||
args = prefix + ": " + args
|
||||
}
|
||||
_ = l.std.Output(l.Formatter.GetDepth()+1, args)
|
||||
}
|
||||
|
||||
func (l logger) WithName(name string) logr.LogSink {
|
||||
l.Formatter.AddName(name)
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l logger) WithValues(kvList ...interface{}) logr.LogSink {
|
||||
l.Formatter.AddValues(kvList)
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l logger) WithCallDepth(depth int) logr.LogSink {
|
||||
l.Formatter.AddCallDepth(depth)
|
||||
return &l
|
||||
}
|
||||
|
||||
// Underlier exposes access to the underlying logging implementation. Since
|
||||
// callers only have a logr.Logger, they have to know which implementation is
|
||||
// in use, so this interface is less of an abstraction and more of way to test
|
||||
// type conversion.
|
||||
type Underlier interface {
|
||||
GetUnderlying() StdLogger
|
||||
}
|
||||
|
||||
// GetUnderlying returns the StdLogger underneath this logger. Since StdLogger
|
||||
// is itself an interface, the result may or may not be a Go log.Logger.
|
||||
func (l logger) GetUnderlying() StdLogger {
|
||||
return l.std
|
||||
}
|
10
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
10
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
@@ -13,7 +13,6 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
@@ -63,7 +62,14 @@ func FileDescriptor(s filePath) fileDescGZIP {
|
||||
// Find the descriptor in the v2 registry.
|
||||
var b []byte
|
||||
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
|
||||
b, _ = Marshal(protodesc.ToFileDescriptorProto(fd))
|
||||
if fd, ok := fd.(interface{ ProtoLegacyRawDesc() []byte }); ok {
|
||||
b = fd.ProtoLegacyRawDesc()
|
||||
} else {
|
||||
// TODO: Use protodesc.ToFileDescriptorProto to construct
|
||||
// a descriptorpb.FileDescriptorProto and marshal it.
|
||||
// However, doing so causes the proto package to have a dependency
|
||||
// on descriptorpb, leading to cyclic dependency issues.
|
||||
}
|
||||
}
|
||||
|
||||
// Locally cache the raw descriptor form for the file.
|
||||
|
14
vendor/github.com/golang/protobuf/ptypes/any.go
generated
vendored
14
vendor/github.com/golang/protobuf/ptypes/any.go
generated
vendored
@@ -19,8 +19,6 @@ const urlPrefix = "type.googleapis.com/"
|
||||
|
||||
// AnyMessageName returns the message name contained in an anypb.Any message.
|
||||
// Most type assertions should use the Is function instead.
|
||||
//
|
||||
// Deprecated: Call the any.MessageName method instead.
|
||||
func AnyMessageName(any *anypb.Any) (string, error) {
|
||||
name, err := anyMessageName(any)
|
||||
return string(name), err
|
||||
@@ -40,8 +38,6 @@ func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) {
|
||||
}
|
||||
|
||||
// MarshalAny marshals the given message m into an anypb.Any message.
|
||||
//
|
||||
// Deprecated: Call the anypb.New function instead.
|
||||
func MarshalAny(m proto.Message) (*anypb.Any, error) {
|
||||
switch dm := m.(type) {
|
||||
case DynamicAny:
|
||||
@@ -62,9 +58,6 @@ func MarshalAny(m proto.Message) (*anypb.Any, error) {
|
||||
// Empty returns a new message of the type specified in an anypb.Any message.
|
||||
// It returns protoregistry.NotFound if the corresponding message type could not
|
||||
// be resolved in the global registry.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead
|
||||
// to resolve the message name and create a new instance of it.
|
||||
func Empty(any *anypb.Any) (proto.Message, error) {
|
||||
name, err := anyMessageName(any)
|
||||
if err != nil {
|
||||
@@ -83,8 +76,6 @@ func Empty(any *anypb.Any) (proto.Message, error) {
|
||||
//
|
||||
// The target message m may be a *DynamicAny message. If the underlying message
|
||||
// type could not be resolved, then this returns protoregistry.NotFound.
|
||||
//
|
||||
// Deprecated: Call the any.UnmarshalTo method instead.
|
||||
func UnmarshalAny(any *anypb.Any, m proto.Message) error {
|
||||
if dm, ok := m.(*DynamicAny); ok {
|
||||
if dm.Message == nil {
|
||||
@@ -109,8 +100,6 @@ func UnmarshalAny(any *anypb.Any, m proto.Message) error {
|
||||
}
|
||||
|
||||
// Is reports whether the Any message contains a message of the specified type.
|
||||
//
|
||||
// Deprecated: Call the any.MessageIs method instead.
|
||||
func Is(any *anypb.Any, m proto.Message) bool {
|
||||
if any == nil || m == nil {
|
||||
return false
|
||||
@@ -130,9 +119,6 @@ func Is(any *anypb.Any, m proto.Message) bool {
|
||||
// var x ptypes.DynamicAny
|
||||
// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
|
||||
// fmt.Printf("unmarshaled message: %v", x.Message)
|
||||
//
|
||||
// Deprecated: Use the any.UnmarshalNew method instead to unmarshal
|
||||
// the any message contents into a new instance of the underlying message.
|
||||
type DynamicAny struct{ proto.Message }
|
||||
|
||||
func (m DynamicAny) String() string {
|
||||
|
4
vendor/github.com/golang/protobuf/ptypes/doc.go
generated
vendored
4
vendor/github.com/golang/protobuf/ptypes/doc.go
generated
vendored
@@ -3,8 +3,4 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package ptypes provides functionality for interacting with well-known types.
|
||||
//
|
||||
// Deprecated: Well-known types have specialized functionality directly
|
||||
// injected into the generated packages for each message type.
|
||||
// See the deprecation notice for each function for the suggested alternative.
|
||||
package ptypes
|
||||
|
4
vendor/github.com/golang/protobuf/ptypes/duration.go
generated
vendored
4
vendor/github.com/golang/protobuf/ptypes/duration.go
generated
vendored
@@ -21,8 +21,6 @@ const (
|
||||
|
||||
// Duration converts a durationpb.Duration to a time.Duration.
|
||||
// Duration returns an error if dur is invalid or overflows a time.Duration.
|
||||
//
|
||||
// Deprecated: Call the dur.AsDuration and dur.CheckValid methods instead.
|
||||
func Duration(dur *durationpb.Duration) (time.Duration, error) {
|
||||
if err := validateDuration(dur); err != nil {
|
||||
return 0, err
|
||||
@@ -41,8 +39,6 @@ func Duration(dur *durationpb.Duration) (time.Duration, error) {
|
||||
}
|
||||
|
||||
// DurationProto converts a time.Duration to a durationpb.Duration.
|
||||
//
|
||||
// Deprecated: Call the durationpb.New function instead.
|
||||
func DurationProto(d time.Duration) *durationpb.Duration {
|
||||
nanos := d.Nanoseconds()
|
||||
secs := nanos / 1e9
|
||||
|
9
vendor/github.com/golang/protobuf/ptypes/timestamp.go
generated
vendored
9
vendor/github.com/golang/protobuf/ptypes/timestamp.go
generated
vendored
@@ -33,8 +33,6 @@ const (
|
||||
//
|
||||
// A nil Timestamp returns an error. The first return value in that case is
|
||||
// undefined.
|
||||
//
|
||||
// Deprecated: Call the ts.AsTime and ts.CheckValid methods instead.
|
||||
func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) {
|
||||
// Don't return the zero value on error, because corresponds to a valid
|
||||
// timestamp. Instead return whatever time.Unix gives us.
|
||||
@@ -48,8 +46,6 @@ func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) {
|
||||
}
|
||||
|
||||
// TimestampNow returns a google.protobuf.Timestamp for the current time.
|
||||
//
|
||||
// Deprecated: Call the timestamppb.Now function instead.
|
||||
func TimestampNow() *timestamppb.Timestamp {
|
||||
ts, err := TimestampProto(time.Now())
|
||||
if err != nil {
|
||||
@@ -60,8 +56,6 @@ func TimestampNow() *timestamppb.Timestamp {
|
||||
|
||||
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
|
||||
// It returns an error if the resulting Timestamp is invalid.
|
||||
//
|
||||
// Deprecated: Call the timestamppb.New function instead.
|
||||
func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) {
|
||||
ts := ×tamppb.Timestamp{
|
||||
Seconds: t.Unix(),
|
||||
@@ -75,9 +69,6 @@ func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) {
|
||||
|
||||
// TimestampString returns the RFC 3339 string for valid Timestamps.
|
||||
// For invalid Timestamps, it returns an error message in parentheses.
|
||||
//
|
||||
// Deprecated: Call the ts.AsTime method instead,
|
||||
// followed by a call to the Format method on the time.Time value.
|
||||
func TimestampString(ts *timestamppb.Timestamp) string {
|
||||
t, err := Timestamp(ts)
|
||||
if err != nil {
|
||||
|
9
vendor/github.com/google/uuid/.travis.yml
generated
vendored
9
vendor/github.com/google/uuid/.travis.yml
generated
vendored
@@ -1,9 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.4.3
|
||||
- 1.5.3
|
||||
- tip
|
||||
|
||||
script:
|
||||
- go test -v ./...
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user