mirror of
https://github.com/fatedier/frp.git
synced 2025-06-07 00:08:20 +00:00
commit
a301046f3d
@ -2,14 +2,16 @@ version: 2
|
|||||||
jobs:
|
jobs:
|
||||||
go-version-latest:
|
go-version-latest:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/go:1.18-node
|
- image: cimg/go:1.19-node
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: make
|
- run: make
|
||||||
- run: make alltest
|
- run: make alltest
|
||||||
go-version-last:
|
go-version-last:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/go:1.17-node
|
- image: cimg/go:1.18-node
|
||||||
|
resource_class: large
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: make
|
- run: make
|
||||||
|
4
.github/workflows/build-and-push-image.yml
vendored
4
.github/workflows/build-and-push-image.yml
vendored
@ -62,7 +62,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./dockerfiles/Dockerfile-for-frpc
|
file: ./dockerfiles/Dockerfile-for-frpc
|
||||||
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
|
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/riscv64,linux/s390x
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.TAG_FRPC }}
|
${{ env.TAG_FRPC }}
|
||||||
@ -73,7 +73,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./dockerfiles/Dockerfile-for-frps
|
file: ./dockerfiles/Dockerfile-for-frps
|
||||||
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
|
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/riscv64,linux/s390x
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.TAG_FRPS }}
|
${{ env.TAG_FRPS }}
|
||||||
|
41
.github/workflows/golangci-lint.yml
vendored
Normal file
41
.github/workflows/golangci-lint.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: golangci-lint
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- dev
|
||||||
|
pull_request:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
# Optional: allow read access to pull request. Use with `only-new-issues` option.
|
||||||
|
pull-requests: read
|
||||||
|
jobs:
|
||||||
|
golangci:
|
||||||
|
name: lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.19
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
with:
|
||||||
|
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
||||||
|
version: v1.49.0
|
||||||
|
|
||||||
|
# Optional: golangci-lint command line arguments.
|
||||||
|
# args: --issues-exit-code=0
|
||||||
|
|
||||||
|
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||||
|
# only-new-issues: true
|
||||||
|
|
||||||
|
# Optional: if set to true then the all caching functionality will be complete disabled,
|
||||||
|
# takes precedence over all other caching options.
|
||||||
|
# skip-cache: true
|
||||||
|
|
||||||
|
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
|
||||||
|
# skip-pkg-cache: true
|
||||||
|
|
||||||
|
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
|
||||||
|
# skip-build-cache: true
|
2
.github/workflows/goreleaser.yml
vendored
2
.github/workflows/goreleaser.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.18
|
go-version: 1.19
|
||||||
|
|
||||||
- run: |
|
- run: |
|
||||||
# https://github.com/actions/setup-go/issues/107
|
# https://github.com/actions/setup-go/issues/107
|
||||||
|
140
.golangci.yml
Normal file
140
.golangci.yml
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
service:
|
||||||
|
# When updating this, also update the version stored in docker/build-tools/Dockerfile in the istio/tools repo.
|
||||||
|
golangci-lint-version: 1.49.x # use the fixed version to not introduce new linters unexpectedly
|
||||||
|
|
||||||
|
run:
|
||||||
|
concurrency: 4
|
||||||
|
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||||
|
deadline: 20m
|
||||||
|
build-tags:
|
||||||
|
- integ
|
||||||
|
- integfuzz
|
||||||
|
# which dirs to skip: they won't be analyzed;
|
||||||
|
# can use regexp here: generated.*, regexp is applied on full path;
|
||||||
|
# default value is empty list, but next dirs are always skipped independently
|
||||||
|
# from this option's value:
|
||||||
|
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
||||||
|
skip-dirs:
|
||||||
|
- genfiles$
|
||||||
|
- vendor$
|
||||||
|
- bin$
|
||||||
|
|
||||||
|
# which files to skip: they will be analyzed, but issues from them
|
||||||
|
# won't be reported. Default value is empty list, but there is
|
||||||
|
# no need to include all autogenerated files, we confidently recognize
|
||||||
|
# autogenerated files. If it's not please let us know.
|
||||||
|
skip-files:
|
||||||
|
- ".*\\.pb\\.go"
|
||||||
|
- ".*\\.gen\\.go"
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- unused
|
||||||
|
- errcheck
|
||||||
|
- exportloopref
|
||||||
|
- gocritic
|
||||||
|
- gofumpt
|
||||||
|
- goimports
|
||||||
|
- revive
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- lll
|
||||||
|
- misspell
|
||||||
|
- staticcheck
|
||||||
|
- stylecheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- gci
|
||||||
|
- gosec
|
||||||
|
- asciicheck
|
||||||
|
- prealloc
|
||||||
|
- predeclared
|
||||||
|
- makezero
|
||||||
|
fast: false
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
errcheck:
|
||||||
|
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
||||||
|
# default is false: such cases aren't reported by default.
|
||||||
|
check-type-assertions: false
|
||||||
|
|
||||||
|
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||||
|
# default is false: such cases aren't reported by default.
|
||||||
|
check-blank: false
|
||||||
|
govet:
|
||||||
|
# report about shadowed variables
|
||||||
|
check-shadowing: false
|
||||||
|
maligned:
|
||||||
|
# print struct with more effective memory layout or not, false by default
|
||||||
|
suggest-new: true
|
||||||
|
misspell:
|
||||||
|
# Correct spellings using locale preferences for US or UK.
|
||||||
|
# Default is to use a neutral variety of English.
|
||||||
|
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||||
|
locale: US
|
||||||
|
ignore-words:
|
||||||
|
- cancelled
|
||||||
|
- marshalled
|
||||||
|
lll:
|
||||||
|
# max line length, lines longer will be reported. Default is 120.
|
||||||
|
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||||
|
line-length: 160
|
||||||
|
# tab width in spaces. Default to 1.
|
||||||
|
tab-width: 1
|
||||||
|
gocritic:
|
||||||
|
disabled-checks:
|
||||||
|
- exitAfterDefer
|
||||||
|
unused:
|
||||||
|
check-exported: false
|
||||||
|
unparam:
|
||||||
|
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
||||||
|
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
||||||
|
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
|
||||||
|
# with golangci-lint call it on a directory with the changed file.
|
||||||
|
check-exported: false
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- default
|
||||||
|
- prefix(github.com/fatedier/frp/)
|
||||||
|
gosec:
|
||||||
|
severity: "low"
|
||||||
|
confidence: "low"
|
||||||
|
excludes:
|
||||||
|
- G102
|
||||||
|
- G112
|
||||||
|
- G306
|
||||||
|
- G401
|
||||||
|
- G402
|
||||||
|
- G404
|
||||||
|
- G501
|
||||||
|
|
||||||
|
issues:
|
||||||
|
# List of regexps of issue texts to exclude, empty list by default.
|
||||||
|
# But independently from this option we use default exclude patterns,
|
||||||
|
# it can be disabled by `exclude-use-default: false`. To list all
|
||||||
|
# excluded by default patterns execute `golangci-lint run --help`
|
||||||
|
# exclude:
|
||||||
|
# - composite literal uses unkeyed fields
|
||||||
|
|
||||||
|
exclude-rules:
|
||||||
|
# Exclude some linters from running on test files.
|
||||||
|
- path: _test\.go$|^tests/|^samples/
|
||||||
|
linters:
|
||||||
|
- errcheck
|
||||||
|
- maligned
|
||||||
|
|
||||||
|
# Independently from option `exclude` we use default exclude patterns,
|
||||||
|
# it can be disabled by this option. To list all
|
||||||
|
# excluded by default patterns execute `golangci-lint run --help`.
|
||||||
|
# Default value for this option is true.
|
||||||
|
exclude-use-default: true
|
||||||
|
|
||||||
|
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||||
|
max-per-linter: 0
|
||||||
|
|
||||||
|
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||||
|
max-same-issues: 0
|
@ -2,7 +2,7 @@ export PATH := $(GOPATH)/bin:$(PATH)
|
|||||||
export GO111MODULE=on
|
export GO111MODULE=on
|
||||||
LDFLAGS := -s -w
|
LDFLAGS := -s -w
|
||||||
|
|
||||||
os-archs=darwin:amd64 darwin:arm64 freebsd:386 freebsd:amd64 linux:386 linux:amd64 linux:arm linux:arm64 windows:386 windows:amd64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat
|
os-archs=darwin:amd64 darwin:arm64 freebsd:386 freebsd:amd64 linux:386 linux:amd64 linux:arm linux:arm64 windows:386 windows:amd64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat linux:riscv64
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
|
17
README.md
17
README.md
@ -6,17 +6,6 @@
|
|||||||
|
|
||||||
[README](README.md) | [中文文档](README_zh.md)
|
[README](README.md) | [中文文档](README_zh.md)
|
||||||
|
|
||||||
<h3 align="center">Platinum Sponsors</h3>
|
|
||||||
<!--platinum sponsors start-->
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://www.doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
|
||||||
<img width="400px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_doppler.png">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!--platinum sponsors end-->
|
|
||||||
|
|
||||||
<h3 align="center">Gold Sponsors</h3>
|
<h3 align="center">Gold Sponsors</h3>
|
||||||
<!--gold sponsors start-->
|
<!--gold sponsors start-->
|
||||||
|
|
||||||
@ -656,7 +645,7 @@ openssl req -new -sha256 -key server.key \
|
|||||||
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \
|
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \
|
||||||
-out server.csr
|
-out server.csr
|
||||||
|
|
||||||
openssl x509 -req -days 365 \
|
openssl x509 -req -days 365 -sha256 \
|
||||||
-in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
|
-in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
|
||||||
-extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \
|
-extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \
|
||||||
-out server.crt
|
-out server.crt
|
||||||
@ -671,7 +660,7 @@ openssl req -new -sha256 -key client.key \
|
|||||||
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \
|
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \
|
||||||
-out client.csr
|
-out client.csr
|
||||||
|
|
||||||
openssl x509 -req -days 365 \
|
openssl x509 -req -days 365 -sha256 \
|
||||||
-in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
|
-in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
|
||||||
-extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \
|
-extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \
|
||||||
-out client.crt
|
-out client.crt
|
||||||
@ -883,7 +872,7 @@ custom_domains = test.example.com
|
|||||||
host_header_rewrite = dev.example.com
|
host_header_rewrite = dev.example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
The HTTP request will have the the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`.
|
The HTTP request will have the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`.
|
||||||
|
|
||||||
### Setting other HTTP Headers
|
### Setting other HTTP Headers
|
||||||
|
|
||||||
|
11
README_zh.md
11
README_zh.md
@ -7,17 +7,6 @@
|
|||||||
|
|
||||||
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
|
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
|
||||||
|
|
||||||
<h3 align="center">Platinum Sponsors</h3>
|
|
||||||
<!--platinum sponsors start-->
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://www.doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
|
||||||
<img width="400px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_doppler.png">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!--platinum sponsors end-->
|
|
||||||
|
|
||||||
<h3 align="center">Gold Sponsors</h3>
|
<h3 align="center">Gold Sponsors</h3>
|
||||||
<!--gold sponsors start-->
|
<!--gold sponsors start-->
|
||||||
|
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
### New
|
### Improve
|
||||||
|
|
||||||
* Use auto generated certificates if `plugin_key_path` and `plugin_crt_path` are empty for plugin `https2https` and `https2http`.
|
* Adjust http group load balancing to forward requests to each frpc proxy round robin. Previous behavior is always forwarding requests to single proxy in the case of single concurrency.
|
||||||
* Server dashboard supports TLS configs.
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
* xtcp error with IPv6 address.
|
|
||||||
|
@ -20,10 +20,10 @@ import (
|
|||||||
"net/http/pprof"
|
"net/http/pprof"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/fatedier/frp/assets"
|
"github.com/fatedier/frp/assets"
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -77,6 +77,8 @@ func (svr *Service) RunAdminServer(address string) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
go server.Serve(ln)
|
go func() {
|
||||||
|
_ = server.Serve(ln)
|
||||||
|
}()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Info("api response [/api/reload], code [%d]", res.Code)
|
log.Info("api response [/api/reload], code [%d]", res.Code)
|
||||||
w.WriteHeader(res.Code)
|
w.WriteHeader(res.Code)
|
||||||
if len(res.Msg) > 0 {
|
if len(res.Msg) > 0 {
|
||||||
w.Write([]byte(res.Msg))
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -68,7 +68,6 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("success reload conf")
|
log.Info("success reload conf")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type StatusResp struct {
|
type StatusResp struct {
|
||||||
@ -173,7 +172,7 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
log.Info("Http response [/api/status]")
|
log.Info("Http response [/api/status]")
|
||||||
buf, _ = json.Marshal(&res)
|
buf, _ = json.Marshal(&res)
|
||||||
w.Write(buf)
|
_, _ = w.Write(buf)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ps := svr.ctl.pm.GetAllProxyStatus()
|
ps := svr.ctl.pm.GetAllProxyStatus()
|
||||||
@ -202,7 +201,6 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
sort.Sort(ByProxyStatusResp(res.STCP))
|
sort.Sort(ByProxyStatusResp(res.STCP))
|
||||||
sort.Sort(ByProxyStatusResp(res.XTCP))
|
sort.Sort(ByProxyStatusResp(res.XTCP))
|
||||||
sort.Sort(ByProxyStatusResp(res.SUDP))
|
sort.Sort(ByProxyStatusResp(res.SUDP))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/config
|
// GET api/config
|
||||||
@ -214,7 +212,7 @@ func (svr *Service) apiGetConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Info("Http get response [/api/config], code [%d]", res.Code)
|
log.Info("Http get response [/api/config], code [%d]", res.Code)
|
||||||
w.WriteHeader(res.Code)
|
w.WriteHeader(res.Code)
|
||||||
if len(res.Msg) > 0 {
|
if len(res.Msg) > 0 {
|
||||||
w.Write([]byte(res.Msg))
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -254,7 +252,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Info("Http put response [/api/config], code [%d]", res.Code)
|
log.Info("Http put response [/api/config], code [%d]", res.Code)
|
||||||
w.WriteHeader(res.Code)
|
w.WriteHeader(res.Code)
|
||||||
if len(res.Msg) > 0 {
|
if len(res.Msg) > 0 {
|
||||||
w.Write([]byte(res.Msg))
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -315,7 +313,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
content = strings.Join(newRows, "\n")
|
content = strings.Join(newRows, "\n")
|
||||||
|
|
||||||
err = os.WriteFile(svr.cfgFile, []byte(content), 0644)
|
err = os.WriteFile(svr.cfgFile, []byte(content), 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res.Code = 500
|
res.Code = 500
|
||||||
res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
|
res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
|
||||||
|
@ -21,9 +21,13 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/control/shutdown"
|
||||||
|
"github.com/fatedier/golib/crypto"
|
||||||
|
libdial "github.com/fatedier/golib/net/dial"
|
||||||
|
fmux "github.com/hashicorp/yamux"
|
||||||
|
|
||||||
"github.com/fatedier/frp/client/proxy"
|
"github.com/fatedier/frp/client/proxy"
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
@ -31,11 +35,6 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/transport"
|
"github.com/fatedier/frp/pkg/transport"
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
|
|
||||||
"github.com/fatedier/golib/control/shutdown"
|
|
||||||
"github.com/fatedier/golib/crypto"
|
|
||||||
libdial "github.com/fatedier/golib/net/dial"
|
|
||||||
fmux "github.com/hashicorp/yamux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Control struct {
|
type Control struct {
|
||||||
@ -79,8 +78,6 @@ type Control struct {
|
|||||||
// The UDP port that the server is listening on
|
// The UDP port that the server is listening on
|
||||||
serverUDPPort int
|
serverUDPPort int
|
||||||
|
|
||||||
mu sync.RWMutex
|
|
||||||
|
|
||||||
xl *xlog.Logger
|
xl *xlog.Logger
|
||||||
|
|
||||||
// service context
|
// service context
|
||||||
@ -95,8 +92,8 @@ func NewControl(ctx context.Context, runID string, conn net.Conn, session *fmux.
|
|||||||
pxyCfgs map[string]config.ProxyConf,
|
pxyCfgs map[string]config.ProxyConf,
|
||||||
visitorCfgs map[string]config.VisitorConf,
|
visitorCfgs map[string]config.VisitorConf,
|
||||||
serverUDPPort int,
|
serverUDPPort int,
|
||||||
authSetter auth.Setter) *Control {
|
authSetter auth.Setter,
|
||||||
|
) *Control {
|
||||||
// new xlog instance
|
// new xlog instance
|
||||||
ctl := &Control{
|
ctl := &Control{
|
||||||
runID: runID,
|
runID: runID,
|
||||||
@ -131,7 +128,6 @@ func (ctl *Control) Run() {
|
|||||||
|
|
||||||
// start all visitors
|
// start all visitors
|
||||||
go ctl.vm.Run()
|
go ctl.vm.Run()
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *Control) HandleReqWorkConn(inMsg *msg.ReqWorkConn) {
|
func (ctl *Control) HandleReqWorkConn(inMsg *msg.ReqWorkConn) {
|
||||||
@ -400,24 +396,21 @@ func (ctl *Control) worker() {
|
|||||||
go ctl.reader()
|
go ctl.reader()
|
||||||
go ctl.writer()
|
go ctl.writer()
|
||||||
|
|
||||||
select {
|
<-ctl.closedCh
|
||||||
case <-ctl.closedCh:
|
// close related channels and wait until other goroutines done
|
||||||
// close related channels and wait until other goroutines done
|
close(ctl.readCh)
|
||||||
close(ctl.readCh)
|
ctl.readerShutdown.WaitDone()
|
||||||
ctl.readerShutdown.WaitDone()
|
ctl.msgHandlerShutdown.WaitDone()
|
||||||
ctl.msgHandlerShutdown.WaitDone()
|
|
||||||
|
|
||||||
close(ctl.sendCh)
|
close(ctl.sendCh)
|
||||||
ctl.writerShutdown.WaitDone()
|
ctl.writerShutdown.WaitDone()
|
||||||
|
|
||||||
ctl.pm.Close()
|
ctl.pm.Close()
|
||||||
ctl.vm.Close()
|
ctl.vm.Close()
|
||||||
|
|
||||||
close(ctl.closedDoneCh)
|
close(ctl.closedDoneCh)
|
||||||
if ctl.session != nil {
|
if ctl.session != nil {
|
||||||
ctl.session.Close()
|
ctl.session.Close()
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,18 +6,9 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Type int
|
var ErrPayloadType = errors.New("error payload type")
|
||||||
|
|
||||||
const (
|
type Handler func(payload interface{}) error
|
||||||
EvStartProxy Type = iota
|
|
||||||
EvCloseProxy
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrPayloadType = errors.New("error payload type")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Handler func(evType Type, payload interface{}) error
|
|
||||||
|
|
||||||
type StartProxyPayload struct {
|
type StartProxyPayload struct {
|
||||||
NewProxyMsg *msg.NewProxy
|
NewProxyMsg *msg.NewProxy
|
||||||
|
@ -26,9 +26,7 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrHealthCheckType = errors.New("error health check type")
|
||||||
ErrHealthCheckType = errors.New("error health check type")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Monitor struct {
|
type Monitor struct {
|
||||||
checkType string
|
checkType string
|
||||||
@ -54,8 +52,8 @@ type Monitor struct {
|
|||||||
func NewMonitor(ctx context.Context, checkType string,
|
func NewMonitor(ctx context.Context, checkType string,
|
||||||
intervalS int, timeoutS int, maxFailedTimes int,
|
intervalS int, timeoutS int, maxFailedTimes int,
|
||||||
addr string, url string,
|
addr string, url string,
|
||||||
statusNormalFn func(), statusFailedFn func()) *Monitor {
|
statusNormalFn func(), statusFailedFn func(),
|
||||||
|
) *Monitor {
|
||||||
if intervalS <= 0 {
|
if intervalS <= 0 {
|
||||||
intervalS = 10
|
intervalS = 10
|
||||||
}
|
}
|
||||||
@ -152,7 +150,7 @@ func (monitor *Monitor) doTCPCheck(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
|
func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
|
||||||
req, err := http.NewRequest("GET", monitor.url, nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", monitor.url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -161,7 +159,7 @@ func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
io.Copy(io.Discard, resp.Body)
|
_, _ = io.Copy(io.Discard, resp.Body)
|
||||||
|
|
||||||
if resp.StatusCode/100 != 2 {
|
if resp.StatusCode/100 != 2 {
|
||||||
return fmt.Errorf("do http health check, StatusCode is [%d] not 2xx", resp.StatusCode)
|
return fmt.Errorf("do http health check, StatusCode is [%d] not 2xx", resp.StatusCode)
|
||||||
|
@ -24,14 +24,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
|
||||||
plugin "github.com/fatedier/frp/pkg/plugin/client"
|
|
||||||
"github.com/fatedier/frp/pkg/proto/udp"
|
|
||||||
"github.com/fatedier/frp/pkg/util/limit"
|
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
|
||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
"github.com/fatedier/golib/errors"
|
||||||
frpIo "github.com/fatedier/golib/io"
|
frpIo "github.com/fatedier/golib/io"
|
||||||
libdial "github.com/fatedier/golib/net/dial"
|
libdial "github.com/fatedier/golib/net/dial"
|
||||||
@ -39,6 +31,14 @@ import (
|
|||||||
fmux "github.com/hashicorp/yamux"
|
fmux "github.com/hashicorp/yamux"
|
||||||
pp "github.com/pires/go-proxyproto"
|
pp "github.com/pires/go-proxyproto"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/config"
|
||||||
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
|
plugin "github.com/fatedier/frp/pkg/plugin/client"
|
||||||
|
"github.com/fatedier/frp/pkg/proto/udp"
|
||||||
|
"github.com/fatedier/frp/pkg/util/limit"
|
||||||
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Proxy defines how to handle work connections for different proxy type.
|
// Proxy defines how to handle work connections for different proxy type.
|
||||||
@ -322,7 +322,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
|
|
||||||
// Wait for client address at most 5 seconds.
|
// Wait for client address at most 5 seconds.
|
||||||
var natHoleRespMsg msg.NatHoleResp
|
var natHoleRespMsg msg.NatHoleResp
|
||||||
clientConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
_ = clientConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||||
|
|
||||||
buf := pool.GetBuf(1024)
|
buf := pool.GetBuf(1024)
|
||||||
n, err := clientConn.Read(buf)
|
n, err := clientConn.Read(buf)
|
||||||
@ -335,8 +335,8 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
xl.Error("get natHoleRespMsg error: %v", err)
|
xl.Error("get natHoleRespMsg error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
clientConn.SetReadDeadline(time.Time{})
|
_ = clientConn.SetReadDeadline(time.Time{})
|
||||||
clientConn.Close()
|
_ = clientConn.Close()
|
||||||
|
|
||||||
if natHoleRespMsg.Error != "" {
|
if natHoleRespMsg.Error != "" {
|
||||||
xl.Error("natHoleRespMsg get error info: %s", natHoleRespMsg.Error)
|
xl.Error("natHoleRespMsg get error info: %s", natHoleRespMsg.Error)
|
||||||
@ -357,10 +357,13 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
xl.Error("get natHoleResp visitor address error: %v", natHoleRespMsg.VisitorAddr)
|
xl.Error("get natHoleResp visitor address error: %v", natHoleRespMsg.VisitorAddr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pxy.sendDetectMsg(host, int(port), laddr, []byte(natHoleRespMsg.Sid))
|
_ = pxy.sendDetectMsg(host, int(port), laddr, []byte(natHoleRespMsg.Sid))
|
||||||
xl.Trace("send all detect msg done")
|
xl.Trace("send all detect msg done")
|
||||||
|
|
||||||
msg.WriteMsg(conn, &msg.NatHoleClientDetectOK{})
|
if err := msg.WriteMsg(conn, &msg.NatHoleClientDetectOK{}); err != nil {
|
||||||
|
xl.Error("write message error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Listen for clientConn's address and wait for visitor connection
|
// Listen for clientConn's address and wait for visitor connection
|
||||||
lConn, err := net.ListenUDP("udp", laddr)
|
lConn, err := net.ListenUDP("udp", laddr)
|
||||||
@ -370,7 +373,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
}
|
}
|
||||||
defer lConn.Close()
|
defer lConn.Close()
|
||||||
|
|
||||||
lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
_ = lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||||
sidBuf := pool.GetBuf(1024)
|
sidBuf := pool.GetBuf(1024)
|
||||||
var uAddr *net.UDPAddr
|
var uAddr *net.UDPAddr
|
||||||
n, uAddr, err = lConn.ReadFromUDP(sidBuf)
|
n, uAddr, err = lConn.ReadFromUDP(sidBuf)
|
||||||
@ -378,7 +381,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
xl.Warn("get sid from visitor error: %v", err)
|
xl.Warn("get sid from visitor error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
lConn.SetReadDeadline(time.Time{})
|
_ = lConn.SetReadDeadline(time.Time{})
|
||||||
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
|
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
|
||||||
xl.Warn("incorrect sid from visitor")
|
xl.Warn("incorrect sid from visitor")
|
||||||
return
|
return
|
||||||
@ -386,7 +389,10 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
pool.PutBuf(sidBuf)
|
pool.PutBuf(sidBuf)
|
||||||
xl.Info("nat hole connection make success, sid [%s]", natHoleRespMsg.Sid)
|
xl.Info("nat hole connection make success, sid [%s]", natHoleRespMsg.Sid)
|
||||||
|
|
||||||
lConn.WriteToUDP(sidBuf[:n], uAddr)
|
if _, err := lConn.WriteToUDP(sidBuf[:n], uAddr); err != nil {
|
||||||
|
xl.Error("write uaddr error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
kcpConn, err := frpNet.NewKCPConnFromUDP(lConn, false, uAddr.String())
|
kcpConn, err := frpNet.NewKCPConnFromUDP(lConn, false, uAddr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -424,12 +430,13 @@ func (pxy *XTCPProxy) sendDetectMsg(addr string, port int, laddr *net.UDPAddr, c
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//uConn := ipv4.NewConn(tConn)
|
// uConn := ipv4.NewConn(tConn)
|
||||||
//uConn.SetTTL(3)
|
// uConn.SetTTL(3)
|
||||||
|
|
||||||
tConn.Write(content)
|
if _, err := tConn.Write(content); err != nil {
|
||||||
tConn.Close()
|
return err
|
||||||
return nil
|
}
|
||||||
|
return tConn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDP
|
// UDP
|
||||||
@ -539,7 +546,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
heartbeatFn := func(conn net.Conn, sendCh chan msg.Message) {
|
heartbeatFn := func(sendCh chan msg.Message) {
|
||||||
var errRet error
|
var errRet error
|
||||||
for {
|
for {
|
||||||
time.Sleep(time.Duration(30) * time.Second)
|
time.Sleep(time.Duration(30) * time.Second)
|
||||||
@ -554,7 +561,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
|
|
||||||
go workConnSenderFn(pxy.workConn, pxy.sendCh)
|
go workConnSenderFn(pxy.workConn, pxy.sendCh)
|
||||||
go workConnReaderFn(pxy.workConn, pxy.readCh)
|
go workConnReaderFn(pxy.workConn, pxy.readCh)
|
||||||
go heartbeatFn(pxy.workConn, pxy.sendCh)
|
go heartbeatFn(pxy.sendCh)
|
||||||
udp.Forwarder(pxy.localAddr, pxy.readCh, pxy.sendCh, int(pxy.clientCfg.UDPPacketSize))
|
udp.Forwarder(pxy.localAddr, pxy.readCh, pxy.sendCh, int(pxy.clientCfg.UDPPacketSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,7 +692,7 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heartbeatFn := func(conn net.Conn, sendCh chan msg.Message) {
|
heartbeatFn := func(sendCh chan msg.Message) {
|
||||||
ticker := time.NewTicker(30 * time.Second)
|
ticker := time.NewTicker(30 * time.Second)
|
||||||
defer func() {
|
defer func() {
|
||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
@ -711,14 +718,15 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
|||||||
|
|
||||||
go workConnSenderFn(workConn, sendCh)
|
go workConnSenderFn(workConn, sendCh)
|
||||||
go workConnReaderFn(workConn, readCh)
|
go workConnReaderFn(workConn, readCh)
|
||||||
go heartbeatFn(workConn, sendCh)
|
go heartbeatFn(sendCh)
|
||||||
|
|
||||||
udp.Forwarder(pxy.localAddr, readCh, sendCh, int(pxy.clientCfg.UDPPacketSize))
|
udp.Forwarder(pxy.localAddr, readCh, sendCh, int(pxy.clientCfg.UDPPacketSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common handler for tcp work connections.
|
// Common handler for tcp work connections.
|
||||||
func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf, proxyPlugin plugin.Plugin,
|
func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf, proxyPlugin plugin.Plugin,
|
||||||
baseInfo *config.BaseProxyConf, limiter *rate.Limiter, workConn net.Conn, encKey []byte, m *msg.StartWorkConn) {
|
baseInfo *config.BaseProxyConf, limiter *rate.Limiter, workConn net.Conn, encKey []byte, m *msg.StartWorkConn,
|
||||||
|
) {
|
||||||
xl := xlog.FromContextSafe(ctx)
|
xl := xlog.FromContextSafe(ctx)
|
||||||
var (
|
var (
|
||||||
remote io.ReadWriteCloser
|
remote io.ReadWriteCloser
|
||||||
@ -773,7 +781,7 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
h.WriteTo(buf)
|
_, _ = h.WriteTo(buf)
|
||||||
extraInfo = buf.Bytes()
|
extraInfo = buf.Bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -800,7 +808,11 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
|
|||||||
localConn.RemoteAddr().String(), workConn.LocalAddr().String(), workConn.RemoteAddr().String())
|
localConn.RemoteAddr().String(), workConn.LocalAddr().String(), workConn.RemoteAddr().String())
|
||||||
|
|
||||||
if len(extraInfo) > 0 {
|
if len(extraInfo) > 0 {
|
||||||
localConn.Write(extraInfo)
|
if _, err := localConn.Write(extraInfo); err != nil {
|
||||||
|
workConn.Close()
|
||||||
|
xl.Error("write extraInfo to local conn error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frpIo.Join(localConn, remote)
|
frpIo.Join(localConn, remote)
|
||||||
|
@ -6,12 +6,12 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/errors"
|
||||||
|
|
||||||
"github.com/fatedier/frp/client/event"
|
"github.com/fatedier/frp/client/event"
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
@ -75,7 +75,7 @@ func (pm *Manager) HandleWorkConn(name string, workConn net.Conn, m *msg.StartWo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *Manager) HandleEvent(evType event.Type, payload interface{}) error {
|
func (pm *Manager) HandleEvent(payload interface{}) error {
|
||||||
var m msg.Message
|
var m msg.Message
|
||||||
switch e := payload.(type) {
|
switch e := payload.(type) {
|
||||||
case *event.StartProxyPayload:
|
case *event.StartProxyPayload:
|
||||||
@ -113,10 +113,8 @@ func (pm *Manager) Reload(pxyCfgs map[string]config.ProxyConf) {
|
|||||||
cfg, ok := pxyCfgs[name]
|
cfg, ok := pxyCfgs[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
del = true
|
del = true
|
||||||
} else {
|
} else if !pxy.Cfg.Compare(cfg) {
|
||||||
if !pxy.Cfg.Compare(cfg) {
|
del = true
|
||||||
del = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if del {
|
if del {
|
||||||
|
@ -8,13 +8,13 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/errors"
|
||||||
|
|
||||||
"github.com/fatedier/frp/client/event"
|
"github.com/fatedier/frp/client/event"
|
||||||
"github.com/fatedier/frp/client/health"
|
"github.com/fatedier/frp/client/health"
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -27,9 +27,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
statusCheckInterval time.Duration = 3 * time.Second
|
statusCheckInterval = 3 * time.Second
|
||||||
waitResponseTimeout = 20 * time.Second
|
waitResponseTimeout = 20 * time.Second
|
||||||
startErrTimeout = 30 * time.Second
|
startErrTimeout = 30 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type WorkingStatus struct {
|
type WorkingStatus struct {
|
||||||
@ -145,7 +145,7 @@ func (pw *Wrapper) Stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pw *Wrapper) close() {
|
func (pw *Wrapper) close() {
|
||||||
pw.handler(event.EvCloseProxy, &event.CloseProxyPayload{
|
_ = pw.handler(&event.CloseProxyPayload{
|
||||||
CloseProxyMsg: &msg.CloseProxy{
|
CloseProxyMsg: &msg.CloseProxy{
|
||||||
ProxyName: pw.Name,
|
ProxyName: pw.Name,
|
||||||
},
|
},
|
||||||
@ -174,7 +174,7 @@ func (pw *Wrapper) checkWorker() {
|
|||||||
var newProxyMsg msg.NewProxy
|
var newProxyMsg msg.NewProxy
|
||||||
pw.Cfg.MarshalToMsg(&newProxyMsg)
|
pw.Cfg.MarshalToMsg(&newProxyMsg)
|
||||||
pw.lastSendStartMsg = now
|
pw.lastSendStartMsg = now
|
||||||
pw.handler(event.EvStartProxy, &event.StartProxyPayload{
|
_ = pw.handler(&event.StartProxyPayload{
|
||||||
NewProxyMsg: &newProxyMsg,
|
NewProxyMsg: &newProxyMsg,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ func (pw *Wrapper) checkWorker() {
|
|||||||
func (pw *Wrapper) statusNormalCallback() {
|
func (pw *Wrapper) statusNormalCallback() {
|
||||||
xl := pw.xl
|
xl := pw.xl
|
||||||
atomic.StoreUint32(&pw.health, 0)
|
atomic.StoreUint32(&pw.health, 0)
|
||||||
errors.PanicToError(func() {
|
_ = errors.PanicToError(func() {
|
||||||
select {
|
select {
|
||||||
case pw.healthNotifyCh <- struct{}{}:
|
case pw.healthNotifyCh <- struct{}{}:
|
||||||
default:
|
default:
|
||||||
@ -213,7 +213,7 @@ func (pw *Wrapper) statusNormalCallback() {
|
|||||||
func (pw *Wrapper) statusFailedCallback() {
|
func (pw *Wrapper) statusFailedCallback() {
|
||||||
xl := pw.xl
|
xl := pw.xl
|
||||||
atomic.StoreUint32(&pw.health, 1)
|
atomic.StoreUint32(&pw.health, 1)
|
||||||
errors.PanicToError(func() {
|
_ = errors.PanicToError(func() {
|
||||||
select {
|
select {
|
||||||
case pw.healthNotifyCh <- struct{}{}:
|
case pw.healthNotifyCh <- struct{}{}:
|
||||||
default:
|
default:
|
||||||
|
@ -28,6 +28,10 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/crypto"
|
||||||
|
libdial "github.com/fatedier/golib/net/dial"
|
||||||
|
fmux "github.com/hashicorp/yamux"
|
||||||
|
|
||||||
"github.com/fatedier/frp/assets"
|
"github.com/fatedier/frp/assets"
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
@ -38,10 +42,6 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
"github.com/fatedier/frp/pkg/util/version"
|
"github.com/fatedier/frp/pkg/util/version"
|
||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
"github.com/fatedier/golib/crypto"
|
|
||||||
libdial "github.com/fatedier/golib/net/dial"
|
|
||||||
|
|
||||||
fmux "github.com/hashicorp/yamux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -81,8 +81,12 @@ type Service struct {
|
|||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(cfg config.ClientCommonConf, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf, cfgFile string) (svr *Service, err error) {
|
func NewService(
|
||||||
|
cfg config.ClientCommonConf,
|
||||||
|
pxyCfgs map[string]config.ProxyConf,
|
||||||
|
visitorCfgs map[string]config.VisitorConf,
|
||||||
|
cfgFile string,
|
||||||
|
) (svr *Service, err error) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
svr = &Service{
|
svr = &Service{
|
||||||
authSetter: auth.NewAuthSetter(cfg.ClientConfig),
|
authSetter: auth.NewAuthSetter(cfg.ClientConfig),
|
||||||
@ -198,13 +202,17 @@ func (svr *Service) keepControllerWorking() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
if atomic.LoadUint32(&svr.exit) != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
xl.Info("try to reconnect to server...")
|
xl.Info("try to reconnect to server...")
|
||||||
conn, session, err := svr.login()
|
conn, session, err := svr.login()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xl.Warn("reconnect to server error: %v, wait %v for another retry", err, delayTime)
|
xl.Warn("reconnect to server error: %v, wait %v for another retry", err, delayTime)
|
||||||
util.RandomSleep(delayTime, 0.9, 1.1)
|
util.RandomSleep(delayTime, 0.9, 1.1)
|
||||||
|
|
||||||
delayTime = delayTime * 2
|
delayTime *= 2
|
||||||
if delayTime > maxDelayTime {
|
if delayTime > maxDelayTime {
|
||||||
delayTime = maxDelayTime
|
delayTime = maxDelayTime
|
||||||
}
|
}
|
||||||
@ -329,11 +337,11 @@ func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var loginRespMsg msg.LoginResp
|
var loginRespMsg msg.LoginResp
|
||||||
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
_ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||||
if err = msg.ReadMsgInto(conn, &loginRespMsg); err != nil {
|
if err = msg.ReadMsgInto(conn, &loginRespMsg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn.SetReadDeadline(time.Time{})
|
_ = conn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
if loginRespMsg.Error != "" {
|
if loginRespMsg.Error != "" {
|
||||||
err = fmt.Errorf("%s", loginRespMsg.Error)
|
err = fmt.Errorf("%s", loginRespMsg.Error)
|
||||||
|
@ -24,17 +24,17 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/errors"
|
||||||
|
frpIo "github.com/fatedier/golib/io"
|
||||||
|
"github.com/fatedier/golib/pool"
|
||||||
|
fmux "github.com/hashicorp/yamux"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
"github.com/fatedier/frp/pkg/proto/udp"
|
"github.com/fatedier/frp/pkg/proto/udp"
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
|
||||||
frpIo "github.com/fatedier/golib/io"
|
|
||||||
"github.com/fatedier/golib/pool"
|
|
||||||
fmux "github.com/hashicorp/yamux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Visitor is used for forward traffics from local port tot remote service.
|
// Visitor is used for forward traffics from local port tot remote service.
|
||||||
@ -71,9 +71,8 @@ func NewVisitor(ctx context.Context, ctl *Control, cfg config.VisitorConf) (visi
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BaseVisitor struct {
|
type BaseVisitor struct {
|
||||||
ctl *Control
|
ctl *Control
|
||||||
l net.Listener
|
l net.Listener
|
||||||
closed bool
|
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -138,13 +137,13 @@ func (sv *STCPVisitor) handleConn(userConn net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
||||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||||
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xl.Warn("get newVisitorConnRespMsg error: %v", err)
|
xl.Warn("get newVisitorConnRespMsg error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
visitorConn.SetReadDeadline(time.Time{})
|
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
if newVisitorConnRespMsg.Error != "" {
|
if newVisitorConnRespMsg.Error != "" {
|
||||||
xl.Warn("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
xl.Warn("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
||||||
@ -239,7 +238,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
|||||||
|
|
||||||
// Wait for client address at most 10 seconds.
|
// Wait for client address at most 10 seconds.
|
||||||
var natHoleRespMsg msg.NatHoleResp
|
var natHoleRespMsg msg.NatHoleResp
|
||||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||||
buf := pool.GetBuf(1024)
|
buf := pool.GetBuf(1024)
|
||||||
n, err := visitorConn.Read(buf)
|
n, err := visitorConn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -252,7 +251,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
|||||||
xl.Warn("get natHoleRespMsg error: %v", err)
|
xl.Warn("get natHoleRespMsg error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
visitorConn.SetReadDeadline(time.Time{})
|
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||||
pool.PutBuf(buf)
|
pool.PutBuf(buf)
|
||||||
|
|
||||||
if natHoleRespMsg.Error != "" {
|
if natHoleRespMsg.Error != "" {
|
||||||
@ -279,17 +278,20 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
|||||||
}
|
}
|
||||||
defer lConn.Close()
|
defer lConn.Close()
|
||||||
|
|
||||||
lConn.Write([]byte(natHoleRespMsg.Sid))
|
if _, err := lConn.Write([]byte(natHoleRespMsg.Sid)); err != nil {
|
||||||
|
xl.Error("write sid error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// read ack sid from client
|
// read ack sid from client
|
||||||
sidBuf := pool.GetBuf(1024)
|
sidBuf := pool.GetBuf(1024)
|
||||||
lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
_ = lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||||
n, err = lConn.Read(sidBuf)
|
n, err = lConn.Read(sidBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xl.Warn("get sid from client error: %v", err)
|
xl.Warn("get sid from client error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
lConn.SetReadDeadline(time.Time{})
|
_ = lConn.SetReadDeadline(time.Time{})
|
||||||
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
|
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
|
||||||
xl.Warn("incorrect sid from client")
|
xl.Warn("incorrect sid from client")
|
||||||
return
|
return
|
||||||
@ -411,7 +413,6 @@ func (sv *SUDPVisitor) dispatcher() {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
|
func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
|
||||||
@ -437,13 +438,13 @@ func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// frpc will send heartbeat in workConn to frpc visitor for keeping alive
|
// frpc will send heartbeat in workConn to frpc visitor for keeping alive
|
||||||
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
|
_ = conn.SetReadDeadline(time.Now().Add(60 * time.Second))
|
||||||
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
|
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
|
||||||
xl.Warn("read from workconn for user udp conn error: %v", errRet)
|
xl.Warn("read from workconn for user udp conn error: %v", errRet)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.SetReadDeadline(time.Time{})
|
_ = conn.SetReadDeadline(time.Time{})
|
||||||
switch m := rawMsg.(type) {
|
switch m := rawMsg.(type) {
|
||||||
case *msg.Ping:
|
case *msg.Ping:
|
||||||
xl.Debug("frpc visitor get ping message from frpc")
|
xl.Debug("frpc visitor get ping message from frpc")
|
||||||
@ -523,12 +524,12 @@ func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
||||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||||
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("frpc read newVisitorConnRespMsg error: %v", err)
|
return nil, fmt.Errorf("frpc read newVisitorConnRespMsg error: %v", err)
|
||||||
}
|
}
|
||||||
visitorConn.SetReadDeadline(time.Time{})
|
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
if newVisitorConnRespMsg.Error != "" {
|
if newVisitorConnRespMsg.Error != "" {
|
||||||
return nil, fmt.Errorf("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
return nil, fmt.Errorf("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
||||||
|
@ -65,7 +65,7 @@ func (vm *VisitorManager) Run() {
|
|||||||
name := cfg.GetBaseInfo().ProxyName
|
name := cfg.GetBaseInfo().ProxyName
|
||||||
if _, exist := vm.visitors[name]; !exist {
|
if _, exist := vm.visitors[name]; !exist {
|
||||||
xl.Info("try to start visitor [%s]", name)
|
xl.Info("try to start visitor [%s]", name)
|
||||||
vm.startVisitor(cfg)
|
_ = vm.startVisitor(cfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vm.mu.Unlock()
|
vm.mu.Unlock()
|
||||||
@ -99,10 +99,8 @@ func (vm *VisitorManager) Reload(cfgs map[string]config.VisitorConf) {
|
|||||||
cfg, ok := cfgs[name]
|
cfg, ok := cfgs[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
del = true
|
del = true
|
||||||
} else {
|
} else if !oldCfg.Compare(cfg) {
|
||||||
if !oldCfg.Compare(cfg) {
|
del = true
|
||||||
del = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if del {
|
if del {
|
||||||
@ -123,13 +121,12 @@ func (vm *VisitorManager) Reload(cfgs map[string]config.VisitorConf) {
|
|||||||
if _, ok := vm.cfgs[name]; !ok {
|
if _, ok := vm.cfgs[name]; !ok {
|
||||||
vm.cfgs[name] = cfg
|
vm.cfgs[name] = cfg
|
||||||
addNames = append(addNames, name)
|
addNames = append(addNames, name)
|
||||||
vm.startVisitor(cfg)
|
_ = vm.startVisitor(cfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(addNames) > 0 {
|
if len(addNames) > 0 {
|
||||||
xl.Info("visitor added: %v", addNames)
|
xl.Info("visitor added: %v", addNames)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VisitorManager) Close() {
|
func (vm *VisitorManager) Close() {
|
||||||
|
@ -19,10 +19,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -22,9 +22,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -26,13 +26,13 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/fatedier/frp/client"
|
"github.com/fatedier/frp/client"
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/util/log"
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
"github.com/fatedier/frp/pkg/util/version"
|
"github.com/fatedier/frp/pkg/util/version"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -107,7 +107,7 @@ var rootCmd = &cobra.Command{
|
|||||||
// Note that it's only designed for testing. It's not guaranteed to be stable.
|
// Note that it's only designed for testing. It's not guaranteed to be stable.
|
||||||
if cfgDir != "" {
|
if cfgDir != "" {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
filepath.WalkDir(cfgDir, func(path string, d fs.DirEntry, err error) error {
|
_ = filepath.WalkDir(cfgDir, func(path string, d fs.DirEntry, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
|
|||||||
|
|
||||||
cfg.Complete()
|
cfg.Complete()
|
||||||
if err = cfg.Validate(); err != nil {
|
if err = cfg.Validate(); err != nil {
|
||||||
err = fmt.Errorf("Parse config error: %v", err)
|
err = fmt.Errorf("parse config error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -203,7 +203,6 @@ func startService(
|
|||||||
visitorCfgs map[string]config.VisitorConf,
|
visitorCfgs map[string]config.VisitorConf,
|
||||||
cfgFile string,
|
cfgFile string,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
|
|
||||||
log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel,
|
log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel,
|
||||||
cfg.LogMaxDays, cfg.DisableLogColor)
|
cfg.LogMaxDays, cfg.DisableLogColor)
|
||||||
|
|
||||||
|
@ -23,11 +23,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fatedier/frp/client"
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
|
||||||
|
|
||||||
"github.com/rodaine/table"
|
"github.com/rodaine/table"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/client"
|
||||||
|
"github.com/fatedier/frp/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -18,10 +18,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -18,10 +18,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -18,10 +18,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -18,9 +18,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -18,10 +18,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -18,14 +18,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/util/log"
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
"github.com/fatedier/frp/pkg/util/version"
|
"github.com/fatedier/frp/pkg/util/version"
|
||||||
"github.com/fatedier/frp/server"
|
"github.com/fatedier/frp/server"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -50,16 +50,13 @@ var (
|
|||||||
dashboardUser string
|
dashboardUser string
|
||||||
dashboardPwd string
|
dashboardPwd string
|
||||||
enablePrometheus bool
|
enablePrometheus bool
|
||||||
assetsDir string
|
|
||||||
logFile string
|
logFile string
|
||||||
logLevel string
|
logLevel string
|
||||||
logMaxDays int64
|
logMaxDays int64
|
||||||
disableLogColor bool
|
disableLogColor bool
|
||||||
token string
|
token string
|
||||||
subDomainHost string
|
subDomainHost string
|
||||||
tcpMux bool
|
|
||||||
allowPorts string
|
allowPorts string
|
||||||
maxPoolCount int64
|
|
||||||
maxPortsPerClient int64
|
maxPortsPerClient int64
|
||||||
tlsOnly bool
|
tlsOnly bool
|
||||||
dashboardTLSMode bool
|
dashboardTLSMode bool
|
||||||
@ -151,7 +148,7 @@ func parseServerCommonCfg(fileType int, source []byte) (cfg config.ServerCommonC
|
|||||||
cfg.Complete()
|
cfg.Complete()
|
||||||
err = cfg.Validate()
|
err = cfg.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Parse config error: %v", err)
|
err = fmt.Errorf("parse config error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -189,7 +186,7 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
|
|||||||
// e.g. 1000-2000,2001,2002,3000-4000
|
// e.g. 1000-2000,2001,2002,3000-4000
|
||||||
ports, errRet := util.ParseRangeNumbers(allowPorts)
|
ports, errRet := util.ParseRangeNumbers(allowPorts)
|
||||||
if errRet != nil {
|
if errRet != nil {
|
||||||
err = fmt.Errorf("Parse conf error: allow_ports: %v", errRet)
|
err = fmt.Errorf("parse conf error: allow_ports: %v", errRet)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.18 AS building
|
FROM golang:1.19 AS building
|
||||||
|
|
||||||
COPY . /building
|
COPY . /building
|
||||||
WORKDIR /building
|
WORKDIR /building
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.18 AS building
|
FROM golang:1.19 AS building
|
||||||
|
|
||||||
COPY . /building
|
COPY . /building
|
||||||
WORKDIR /building
|
WORKDIR /building
|
||||||
|
68
go.mod
68
go.mod
@ -1,6 +1,6 @@
|
|||||||
module github.com/fatedier/frp
|
module github.com/fatedier/frp
|
||||||
|
|
||||||
go 1.16
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||||
@ -8,26 +8,60 @@ require (
|
|||||||
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb
|
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb
|
||||||
github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac
|
github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac
|
||||||
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible
|
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible
|
||||||
github.com/go-playground/validator/v10 v10.6.1
|
github.com/go-playground/validator/v10 v10.11.0
|
||||||
github.com/google/uuid v1.2.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c
|
github.com/hashicorp/yamux v0.1.1
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
|
||||||
github.com/onsi/ginkgo v1.16.4
|
github.com/onsi/ginkgo v1.16.4
|
||||||
github.com/onsi/gomega v1.13.0
|
github.com/onsi/gomega v1.20.2
|
||||||
github.com/pires/go-proxyproto v0.6.2
|
github.com/pires/go-proxyproto v0.6.2
|
||||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
github.com/prometheus/client_golang v1.13.0
|
||||||
github.com/prometheus/client_golang v1.11.0
|
|
||||||
github.com/rodaine/table v1.0.1
|
github.com/rodaine/table v1.0.1
|
||||||
github.com/spf13/cobra v1.1.3
|
github.com/spf13/cobra v1.1.3
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
gopkg.in/ini.v1 v1.67.0
|
||||||
gopkg.in/ini.v1 v1.62.0
|
k8s.io/apimachinery v0.25.0
|
||||||
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
|
k8s.io/client-go v0.25.0
|
||||||
k8s.io/apimachinery v0.21.2
|
)
|
||||||
k8s.io/client-go v0.21.2
|
|
||||||
|
require (
|
||||||
|
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.0 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
|
github.com/google/go-cmp v0.5.8 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.0.6 // indirect
|
||||||
|
github.com/klauspost/reedsolomon v1.9.15 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||||
|
github.com/nxadm/tail v1.4.8 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||||
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
||||||
|
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
|
||||||
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
|
||||||
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
|
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
|
||||||
)
|
)
|
||||||
|
267
go.sum
267
go.sum
@ -9,34 +9,34 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T
|
|||||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||||
|
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||||
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||||
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
|
||||||
github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
|
|
||||||
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
|
|
||||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
|
||||||
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
|
||||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
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/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=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
@ -47,7 +47,6 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
|
|||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
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 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
@ -55,10 +54,10 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
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/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
@ -78,14 +77,10 @@ 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
|
||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
|
||||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
|
||||||
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb h1:wCrNShQidLmvVWn/0PikGmpdP0vtQmnvyRg3ZBEhczw=
|
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb h1:wCrNShQidLmvVWn/0PikGmpdP0vtQmnvyRg3ZBEhczw=
|
||||||
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb/go.mod h1:wx3gB6dbIfBRcucp94PI9Bt3I0F2c/MyNEWuhzpWiwk=
|
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb/go.mod h1:wx3gB6dbIfBRcucp94PI9Bt3I0F2c/MyNEWuhzpWiwk=
|
||||||
github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac h1:td1FJwN/oz8+9GldeEm3YdBX0Husc0FSPywLesZxi4w=
|
github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac h1:td1FJwN/oz8+9GldeEm3YdBX0Husc0FSPywLesZxi4w=
|
||||||
@ -93,7 +88,6 @@ github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac/go.mod h1:fLV0TLw
|
|||||||
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74=
|
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74=
|
||||||
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=
|
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
@ -104,31 +98,24 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
|||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||||
|
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
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.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
|
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
|
||||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
|
||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
|
||||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
|
||||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
|
||||||
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
|
||||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
|
||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I=
|
github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
|
||||||
github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
|
github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
@ -139,11 +126,14 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.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.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
@ -163,33 +153,34 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
|||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
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.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||||
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
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/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
@ -213,11 +204,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
|
|||||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c h1:nqkErwUGfpZZMqj29WZ9U/wz2OpJVDuiokLhE/3Y7IQ=
|
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||||
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
@ -225,14 +215,13 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX
|
|||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
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.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
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/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
|
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
@ -242,18 +231,16 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
|||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
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/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
@ -269,39 +256,31 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
|
|||||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
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/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 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
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/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
|
||||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
|
||||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
github.com/onsi/gomega v1.20.2 h1:8uQq0zMgLEfa0vRrrBgaJF2gyW9Da9BmfGV+OyUzfkY=
|
||||||
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
|
||||||
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
||||||
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||||
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
@ -315,8 +294,10 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
|||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
|
|
||||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
|
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||||
|
github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
|
||||||
|
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
@ -326,19 +307,26 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
|
|||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
|
|
||||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||||
|
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||||
|
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
|
||||||
|
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
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/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||||
|
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rodaine/table v1.0.1 h1:U/VwCnUxlVYxw8+NJiLIuCxA/xa6jL38MY3FYysVWWQ=
|
github.com/rodaine/table v1.0.1 h1:U/VwCnUxlVYxw8+NJiLIuCxA/xa6jL38MY3FYysVWWQ=
|
||||||
github.com/rodaine/table v1.0.1/go.mod h1:UVEtfBsflpeEcD56nF4F5AocNFta0ZuolpSVdPtlmP4=
|
github.com/rodaine/table v1.0.1/go.mod h1:UVEtfBsflpeEcD56nF4F5AocNFta0ZuolpSVdPtlmP4=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
@ -346,9 +334,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
|||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
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.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
@ -358,14 +344,12 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
|
|||||||
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
|
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
|
||||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
@ -383,14 +367,16 @@ github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVc
|
|||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
|
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
|
||||||
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.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=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
@ -399,13 +385,12 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
|
||||||
|
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -452,8 +437,8 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
@ -461,25 +446,38 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-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.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -496,13 +494,11 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -514,33 +510,41 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/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-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -553,7 +557,6 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
|
|||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@ -574,14 +577,21 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK
|
|||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
@ -592,13 +602,21 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb
|
|||||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@ -616,8 +634,18 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx
|
|||||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
@ -626,6 +654,9 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
|||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
|
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
@ -635,22 +666,23 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
|||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-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=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y=
|
gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y=
|
||||||
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
@ -661,31 +693,26 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
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.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=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
k8s.io/apimachinery v0.21.2 h1:vezUc/BHqWlQDnZ+XkrpXSmnANSLbpnlpwo0Lhk0gpc=
|
k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU=
|
||||||
k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM=
|
k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0=
|
||||||
k8s.io/client-go v0.21.2 h1:Q1j4L/iMN4pTw6Y4DWppBoUxgKO8LbffEMVEV00MUp0=
|
k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E=
|
||||||
k8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA=
|
k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
|
||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||||
k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
|
||||||
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
|
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
|
||||||
|
@ -5,7 +5,7 @@ ROOT=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/.. && pwd)
|
|||||||
which ginkgo &> /dev/null
|
which ginkgo &> /dev/null
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "ginkgo not found, try to install..."
|
echo "ginkgo not found, try to install..."
|
||||||
go install github.com/onsi/ginkgo/ginkgo@latest
|
go install github.com/onsi/ginkgo/ginkgo@v1.16.5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
debug=false
|
debug=false
|
||||||
|
@ -15,7 +15,7 @@ rm -rf ./release/packages
|
|||||||
mkdir -p ./release/packages
|
mkdir -p ./release/packages
|
||||||
|
|
||||||
os_all='linux windows darwin freebsd'
|
os_all='linux windows darwin freebsd'
|
||||||
arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle'
|
arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle riscv64'
|
||||||
|
|
||||||
cd ./release
|
cd ./release
|
||||||
|
|
||||||
|
@ -18,10 +18,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
|
||||||
|
|
||||||
"github.com/coreos/go-oidc"
|
"github.com/coreos/go-oidc"
|
||||||
"golang.org/x/oauth2/clientcredentials"
|
"golang.org/x/oauth2/clientcredentials"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OidcClientConfig struct {
|
type OidcClientConfig struct {
|
||||||
@ -34,7 +34,7 @@ type OidcClientConfig struct {
|
|||||||
// is "".
|
// is "".
|
||||||
OidcClientSecret string `ini:"oidc_client_secret" json:"oidc_client_secret"`
|
OidcClientSecret string `ini:"oidc_client_secret" json:"oidc_client_secret"`
|
||||||
// OidcAudience specifies the audience of the token in OIDC authentication
|
// OidcAudience specifies the audience of the token in OIDC authentication
|
||||||
//if AuthenticationMethod == "oidc". By default, this value is "".
|
// if AuthenticationMethod == "oidc". By default, this value is "".
|
||||||
OidcAudience string `ini:"oidc_audience" json:"oidc_audience"`
|
OidcAudience string `ini:"oidc_audience" json:"oidc_audience"`
|
||||||
// OidcTokenEndpointURL specifies the URL which implements OIDC Token Endpoint.
|
// OidcTokenEndpointURL specifies the URL which implements OIDC Token Endpoint.
|
||||||
// It will be used to get an OIDC token if AuthenticationMethod == "oidc".
|
// It will be used to get an OIDC token if AuthenticationMethod == "oidc".
|
||||||
|
@ -20,10 +20,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
|
|
||||||
"gopkg.in/ini.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClientCommonConf contains information for a client service. It is
|
// ClientCommonConf contains information for a client service. It is
|
||||||
@ -113,7 +113,7 @@ type ClientCommonConf struct {
|
|||||||
// all supplied proxies are enabled. By default, this value is an empty
|
// all supplied proxies are enabled. By default, this value is an empty
|
||||||
// set.
|
// set.
|
||||||
Start []string `ini:"start" json:"start"`
|
Start []string `ini:"start" json:"start"`
|
||||||
//Start map[string]struct{} `json:"start"`
|
// Start map[string]struct{} `json:"start"`
|
||||||
// Protocol specifies the protocol to use when interacting with the server.
|
// Protocol specifies the protocol to use when interacting with the server.
|
||||||
// Valid values are "tcp", "kcp" and "websocket". By default, this value
|
// Valid values are "tcp", "kcp" and "websocket". By default, this value
|
||||||
// is "tcp".
|
// is "tcp".
|
||||||
@ -214,7 +214,7 @@ func (cfg *ClientCommonConf) Validate() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.TLSEnable == false {
|
if !cfg.TLSEnable {
|
||||||
if cfg.TLSCertFile != "" {
|
if cfg.TLSCertFile != "" {
|
||||||
fmt.Println("WARNING! tls_cert_file is invalid when tls_enable is false")
|
fmt.Println("WARNING! tls_cert_file is invalid when tls_enable is false")
|
||||||
}
|
}
|
||||||
@ -281,7 +281,6 @@ func LoadAllProxyConfsFromIni(
|
|||||||
source interface{},
|
source interface{},
|
||||||
start []string,
|
start []string,
|
||||||
) (map[string]ProxyConf, map[string]VisitorConf, error) {
|
) (map[string]ProxyConf, map[string]VisitorConf, error) {
|
||||||
|
|
||||||
f, err := ini.LoadSources(ini.LoadOptions{
|
f, err := ini.LoadSources(ini.LoadOptions{
|
||||||
Insensitive: false,
|
Insensitive: false,
|
||||||
InsensitiveSections: false,
|
InsensitiveSections: false,
|
||||||
@ -366,7 +365,6 @@ func LoadAllProxyConfsFromIni(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
||||||
|
|
||||||
// Validation
|
// Validation
|
||||||
localPortStr := section.Key("local_port").String()
|
localPortStr := section.Key("local_port").String()
|
||||||
remotePortStr := section.Key("remote_port").String()
|
remotePortStr := section.Key("remote_port").String()
|
||||||
@ -404,8 +402,12 @@ func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copySection(section, tmpsection)
|
copySection(section, tmpsection)
|
||||||
tmpsection.NewKey("local_port", fmt.Sprintf("%d", localPorts[i]))
|
if _, err := tmpsection.NewKey("local_port", fmt.Sprintf("%d", localPorts[i])); err != nil {
|
||||||
tmpsection.NewKey("remote_port", fmt.Sprintf("%d", remotePorts[i]))
|
return fmt.Errorf("local_port new key in section error: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := tmpsection.NewKey("remote_port", fmt.Sprintf("%d", remotePorts[i])); err != nil {
|
||||||
|
return fmt.Errorf("remote_port new key in section error: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -413,6 +415,6 @@ func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
|||||||
|
|
||||||
func copySection(source, target *ini.Section) {
|
func copySection(source, target *ini.Section) {
|
||||||
for key, value := range source.KeysHash() {
|
for key, value := range source.KeysHash() {
|
||||||
target.NewKey(key, value)
|
_, _ = target.NewKey(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,17 @@ package config
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
testUser = "test"
|
testUser = "test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var testClientBytesWithFull = []byte(`
|
||||||
testClientBytesWithFull = []byte(`
|
|
||||||
# [common] is integral section
|
# [common] is integral section
|
||||||
[common]
|
[common]
|
||||||
server_addr = 0.0.0.9
|
server_addr = 0.0.0.9
|
||||||
@ -237,7 +236,6 @@ var (
|
|||||||
use_encryption = false
|
use_encryption = false
|
||||||
use_compression = false
|
use_compression = false
|
||||||
`)
|
`)
|
||||||
)
|
|
||||||
|
|
||||||
func Test_LoadClientCommonConf(t *testing.T) {
|
func Test_LoadClientCommonConf(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
@ -42,7 +42,7 @@ func ParseClientConfig(filePath string) (
|
|||||||
}
|
}
|
||||||
cfg.Complete()
|
cfg.Complete()
|
||||||
if err = cfg.Validate(); err != nil {
|
if err = cfg.Validate(); err != nil {
|
||||||
err = fmt.Errorf("Parse config error: %v", err)
|
err = fmt.Errorf("parse config error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
|
|
||||||
"gopkg.in/ini.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Proxy
|
// Proxy
|
||||||
@ -420,10 +420,6 @@ func (cfg *BaseProxyConf) checkForCli() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *BaseProxyConf) checkForSvr(conf ServerCommonConf) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainConf
|
// DomainConf
|
||||||
func (cfg *DomainConf) check() (err error) {
|
func (cfg *DomainConf) check() (err error) {
|
||||||
if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" {
|
if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" {
|
||||||
|
@ -17,10 +17,10 @@ package config
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -49,7 +49,6 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
|||||||
source []byte
|
source []byte
|
||||||
expected ProxyConf
|
expected ProxyConf
|
||||||
}{
|
}{
|
||||||
|
|
||||||
{
|
{
|
||||||
sname: "ssh",
|
sname: "ssh",
|
||||||
source: []byte(`
|
source: []byte(`
|
||||||
@ -457,5 +456,4 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(c.expected, actual)
|
assert.Equal(c.expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
|
||||||
"gopkg.in/ini.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServerCommonConf contains information for a server service. It is
|
// ServerCommonConf contains information for a server service. It is
|
||||||
@ -236,7 +236,6 @@ func GetDefaultServerConf() ServerCommonConf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UnmarshalServerConfFromIni(source interface{}) (ServerCommonConf, error) {
|
func UnmarshalServerConfFromIni(source interface{}) (ServerCommonConf, error) {
|
||||||
|
|
||||||
f, err := ini.LoadSources(ini.LoadOptions{
|
f, err := ini.LoadSources(ini.LoadOptions{
|
||||||
Insensitive: false,
|
Insensitive: false,
|
||||||
InsensitiveSections: false,
|
InsensitiveSections: false,
|
||||||
@ -308,7 +307,7 @@ func (cfg *ServerCommonConf) Complete() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *ServerCommonConf) Validate() error {
|
func (cfg *ServerCommonConf) Validate() error {
|
||||||
if cfg.DashboardTLSMode == false {
|
if !cfg.DashboardTLSMode {
|
||||||
if cfg.DashboardTLSCertFile != "" {
|
if cfg.DashboardTLSCertFile != "" {
|
||||||
fmt.Println("WARNING! dashboard_tls_cert_file is invalid when dashboard_tls_mode is false")
|
fmt.Println("WARNING! dashboard_tls_cert_file is invalid when dashboard_tls_mode is false")
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,10 @@ package config
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_LoadServerCommonConf(t *testing.T) {
|
func Test_LoadServerCommonConf(t *testing.T) {
|
||||||
@ -126,10 +126,10 @@ func Test_LoadServerCommonConf(t *testing.T) {
|
|||||||
HeartbeatTimeout: 99,
|
HeartbeatTimeout: 99,
|
||||||
UserConnTimeout: 9,
|
UserConnTimeout: 9,
|
||||||
AllowPorts: map[int]struct{}{
|
AllowPorts: map[int]struct{}{
|
||||||
10: struct{}{},
|
10: {},
|
||||||
11: struct{}{},
|
11: {},
|
||||||
12: struct{}{},
|
12: {},
|
||||||
99: struct{}{},
|
99: {},
|
||||||
},
|
},
|
||||||
MaxPoolCount: 59,
|
MaxPoolCount: 59,
|
||||||
MaxPortsPerClient: 9,
|
MaxPortsPerClient: 9,
|
||||||
|
@ -75,21 +75,22 @@ func (q *BandwidthQuantity) UnmarshalString(s string) error {
|
|||||||
f float64
|
f float64
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if strings.HasSuffix(s, "MB") {
|
switch {
|
||||||
|
case strings.HasSuffix(s, "MB"):
|
||||||
base = MB
|
base = MB
|
||||||
fstr := strings.TrimSuffix(s, "MB")
|
fstr := strings.TrimSuffix(s, "MB")
|
||||||
f, err = strconv.ParseFloat(fstr, 64)
|
f, err = strconv.ParseFloat(fstr, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if strings.HasSuffix(s, "KB") {
|
case strings.HasSuffix(s, "KB"):
|
||||||
base = KB
|
base = KB
|
||||||
fstr := strings.TrimSuffix(s, "KB")
|
fstr := strings.TrimSuffix(s, "KB")
|
||||||
f, err = strconv.ParseFloat(fstr, 64)
|
f, err = strconv.ParseFloat(fstr, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
return errors.New("unit not support")
|
return errors.New("unit not support")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,7 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var glbEnvs map[string]string
|
||||||
glbEnvs map[string]string
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
glbEnvs = make(map[string]string)
|
glbEnvs = make(map[string]string)
|
||||||
|
@ -18,9 +18,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
|
||||||
|
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Visitor
|
// Visitor
|
||||||
@ -136,6 +136,7 @@ func (cfg *BaseVisitorConf) check() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *BaseVisitorConf) unmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
func (cfg *BaseVisitorConf) unmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||||
|
_ = section
|
||||||
|
|
||||||
// Custom decoration after basic unmarshal:
|
// Custom decoration after basic unmarshal:
|
||||||
// proxy name
|
// proxy name
|
||||||
|
@ -17,10 +17,10 @@ package config
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
)
|
)
|
||||||
|
|
||||||
const testVisitorPrefix = "test."
|
const testVisitorPrefix = "test."
|
||||||
|
@ -16,26 +16,26 @@ package consts
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// proxy status
|
// proxy status
|
||||||
Idle string = "idle"
|
Idle = "idle"
|
||||||
Working string = "working"
|
Working = "working"
|
||||||
Closed string = "closed"
|
Closed = "closed"
|
||||||
Online string = "online"
|
Online = "online"
|
||||||
Offline string = "offline"
|
Offline = "offline"
|
||||||
|
|
||||||
// proxy type
|
// proxy type
|
||||||
TCPProxy string = "tcp"
|
TCPProxy = "tcp"
|
||||||
UDPProxy string = "udp"
|
UDPProxy = "udp"
|
||||||
TCPMuxProxy string = "tcpmux"
|
TCPMuxProxy = "tcpmux"
|
||||||
HTTPProxy string = "http"
|
HTTPProxy = "http"
|
||||||
HTTPSProxy string = "https"
|
HTTPSProxy = "https"
|
||||||
STCPProxy string = "stcp"
|
STCPProxy = "stcp"
|
||||||
XTCPProxy string = "xtcp"
|
XTCPProxy = "xtcp"
|
||||||
SUDPProxy string = "sudp"
|
SUDPProxy = "sudp"
|
||||||
|
|
||||||
// authentication method
|
// authentication method
|
||||||
TokenAuthMethod string = "token"
|
TokenAuthMethod = "token"
|
||||||
OidcAuthMethod string = "oidc"
|
OidcAuthMethod = "oidc"
|
||||||
|
|
||||||
// TCP multiplexer
|
// TCP multiplexer
|
||||||
HTTPConnectTCPMultiplexer string = "httpconnect"
|
HTTPConnectTCPMultiplexer = "httpconnect"
|
||||||
)
|
)
|
||||||
|
@ -30,7 +30,7 @@ func EnablePrometheus() {
|
|||||||
sm.Add(prometheus.ServerMetrics)
|
sm.Add(prometheus.ServerMetrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sm *serverMetrics = &serverMetrics{}
|
var sm = &serverMetrics{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
metrics.Register(sm)
|
metrics.Register(sm)
|
||||||
|
@ -23,9 +23,12 @@ import (
|
|||||||
server "github.com/fatedier/frp/server/metrics"
|
server "github.com/fatedier/frp/server/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sm *serverMetrics = newServerMetrics()
|
var (
|
||||||
var ServerMetrics server.ServerMetrics
|
sm = newServerMetrics()
|
||||||
var StatsCollector Collector
|
|
||||||
|
ServerMetrics server.ServerMetrics
|
||||||
|
StatsCollector Collector
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ServerMetrics = sm
|
ServerMetrics = sm
|
||||||
|
@ -4,5 +4,7 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/metrics/aggregate"
|
"github.com/fatedier/frp/pkg/metrics/aggregate"
|
||||||
)
|
)
|
||||||
|
|
||||||
var EnableMem = aggregate.EnableMem
|
var (
|
||||||
var EnablePrometheus = aggregate.EnablePrometheus
|
EnableMem = aggregate.EnableMem
|
||||||
|
EnablePrometheus = aggregate.EnablePrometheus
|
||||||
|
)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fatedier/frp/server/metrics"
|
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/server/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -22,9 +22,7 @@ import (
|
|||||||
|
|
||||||
type Message = jsonMsg.Message
|
type Message = jsonMsg.Message
|
||||||
|
|
||||||
var (
|
var msgCtl *jsonMsg.MsgCtl
|
||||||
msgCtl *jsonMsg.MsgCtl
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
msgCtl = jsonMsg.NewMsgCtl()
|
msgCtl = jsonMsg.NewMsgCtl()
|
||||||
|
@ -37,28 +37,26 @@ const (
|
|||||||
TypeNatHoleSid = '5'
|
TypeNatHoleSid = '5'
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var msgTypeMap = map[byte]interface{}{
|
||||||
msgTypeMap = map[byte]interface{}{
|
TypeLogin: Login{},
|
||||||
TypeLogin: Login{},
|
TypeLoginResp: LoginResp{},
|
||||||
TypeLoginResp: LoginResp{},
|
TypeNewProxy: NewProxy{},
|
||||||
TypeNewProxy: NewProxy{},
|
TypeNewProxyResp: NewProxyResp{},
|
||||||
TypeNewProxyResp: NewProxyResp{},
|
TypeCloseProxy: CloseProxy{},
|
||||||
TypeCloseProxy: CloseProxy{},
|
TypeNewWorkConn: NewWorkConn{},
|
||||||
TypeNewWorkConn: NewWorkConn{},
|
TypeReqWorkConn: ReqWorkConn{},
|
||||||
TypeReqWorkConn: ReqWorkConn{},
|
TypeStartWorkConn: StartWorkConn{},
|
||||||
TypeStartWorkConn: StartWorkConn{},
|
TypeNewVisitorConn: NewVisitorConn{},
|
||||||
TypeNewVisitorConn: NewVisitorConn{},
|
TypeNewVisitorConnResp: NewVisitorConnResp{},
|
||||||
TypeNewVisitorConnResp: NewVisitorConnResp{},
|
TypePing: Ping{},
|
||||||
TypePing: Ping{},
|
TypePong: Pong{},
|
||||||
TypePong: Pong{},
|
TypeUDPPacket: UDPPacket{},
|
||||||
TypeUDPPacket: UDPPacket{},
|
TypeNatHoleVisitor: NatHoleVisitor{},
|
||||||
TypeNatHoleVisitor: NatHoleVisitor{},
|
TypeNatHoleClient: NatHoleClient{},
|
||||||
TypeNatHoleClient: NatHoleClient{},
|
TypeNatHoleResp: NatHoleResp{},
|
||||||
TypeNatHoleResp: NatHoleResp{},
|
TypeNatHoleClientDetectOK: NatHoleClientDetectOK{},
|
||||||
TypeNatHoleClientDetectOK: NatHoleClientDetectOK{},
|
TypeNatHoleSid: NatHoleSid{},
|
||||||
TypeNatHoleSid: NatHoleSid{},
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// When frpc start, client send this message to login to server.
|
// When frpc start, client send this message to login to server.
|
||||||
type Login struct {
|
type Login struct {
|
||||||
@ -129,8 +127,7 @@ type NewWorkConn struct {
|
|||||||
Timestamp int64 `json:"timestamp,omitempty"`
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReqWorkConn struct {
|
type ReqWorkConn struct{}
|
||||||
}
|
|
||||||
|
|
||||||
type StartWorkConn struct {
|
type StartWorkConn struct {
|
||||||
ProxyName string `json:"proxy_name,omitempty"`
|
ProxyName string `json:"proxy_name,omitempty"`
|
||||||
@ -187,8 +184,7 @@ type NatHoleResp struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NatHoleClientDetectOK struct {
|
type NatHoleClientDetectOK struct{}
|
||||||
}
|
|
||||||
|
|
||||||
type NatHoleSid struct {
|
type NatHoleSid struct {
|
||||||
Sid string `json:"sid,omitempty"`
|
Sid string `json:"sid,omitempty"`
|
||||||
|
@ -7,15 +7,15 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/errors"
|
||||||
|
"github.com/fatedier/golib/pool"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
"github.com/fatedier/frp/pkg/util/log"
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
|
||||||
"github.com/fatedier/golib/pool"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Timeout seconds.
|
// NatHoleTimeout seconds.
|
||||||
var NatHoleTimeout int64 = 10
|
var NatHoleTimeout int64 = 10
|
||||||
|
|
||||||
type SidRequest struct {
|
type SidRequest struct {
|
||||||
@ -107,7 +107,7 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
|||||||
session := &Session{
|
session := &Session{
|
||||||
Sid: sid,
|
Sid: sid,
|
||||||
VisitorAddr: raddr,
|
VisitorAddr: raddr,
|
||||||
NotifyCh: make(chan struct{}, 0),
|
NotifyCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
nc.mu.Lock()
|
nc.mu.Lock()
|
||||||
clientCfg, ok := nc.clientCfgs[m.ProxyName]
|
clientCfg, ok := nc.clientCfgs[m.ProxyName]
|
||||||
@ -115,14 +115,14 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
|||||||
nc.mu.Unlock()
|
nc.mu.Unlock()
|
||||||
errInfo := fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)
|
errInfo := fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)
|
||||||
log.Debug(errInfo)
|
log.Debug(errInfo)
|
||||||
nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
_, _ = nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if m.SignKey != util.GetAuthKey(clientCfg.Sk, m.Timestamp) {
|
if m.SignKey != util.GetAuthKey(clientCfg.Sk, m.Timestamp) {
|
||||||
nc.mu.Unlock()
|
nc.mu.Unlock()
|
||||||
errInfo := fmt.Sprintf("xtcp connection of [%s] auth failed", m.ProxyName)
|
errInfo := fmt.Sprintf("xtcp connection of [%s] auth failed", m.ProxyName)
|
||||||
log.Debug(errInfo)
|
log.Debug(errInfo)
|
||||||
nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
_, _ = nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
|||||||
case <-session.NotifyCh:
|
case <-session.NotifyCh:
|
||||||
resp := nc.GenNatHoleResponse(session, "")
|
resp := nc.GenNatHoleResponse(session, "")
|
||||||
log.Trace("send nat hole response to visitor")
|
log.Trace("send nat hole response to visitor")
|
||||||
nc.listener.WriteToUDP(resp, raddr)
|
_, _ = nc.listener.WriteToUDP(resp, raddr)
|
||||||
case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
|
case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ func (nc *Controller) HandleClient(m *msg.NatHoleClient, raddr *net.UDPAddr) {
|
|||||||
|
|
||||||
resp := nc.GenNatHoleResponse(session, "")
|
resp := nc.GenNatHoleResponse(session, "")
|
||||||
log.Trace("send nat hole response to client")
|
log.Trace("send nat hole response to client")
|
||||||
nc.listener.WriteToUDP(resp, raddr)
|
_, _ = nc.listener.WriteToUDP(resp, raddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nc *Controller) GenNatHoleResponse(session *Session, errInfo string) []byte {
|
func (nc *Controller) GenNatHoleResponse(session *Session, errInfo string) []byte {
|
||||||
|
@ -86,17 +86,20 @@ func NewHTTP2HTTPSPlugin(params map[string]string) (Plugin, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.s = &http.Server{
|
p.s = &http.Server{
|
||||||
Handler: rp,
|
Handler: rp,
|
||||||
|
ReadHeaderTimeout: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
go p.s.Serve(listener)
|
go func() {
|
||||||
|
_ = p.s.Serve(listener)
|
||||||
|
}()
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTP2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
func (p *HTTP2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||||
p.l.PutConn(wrapConn)
|
_ = p.l.PutConn(wrapConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTP2HTTPSPlugin) Name() string {
|
func (p *HTTP2HTTPSPlugin) Name() string {
|
||||||
|
@ -22,10 +22,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
|
||||||
|
|
||||||
frpIo "github.com/fatedier/golib/io"
|
frpIo "github.com/fatedier/golib/io"
|
||||||
gnet "github.com/fatedier/golib/net"
|
gnet "github.com/fatedier/golib/net"
|
||||||
|
|
||||||
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
const PluginHTTPProxy = "http_proxy"
|
const PluginHTTPProxy = "http_proxy"
|
||||||
@ -56,7 +56,9 @@ func NewHTTPProxyPlugin(params map[string]string) (Plugin, error) {
|
|||||||
Handler: hp,
|
Handler: hp,
|
||||||
}
|
}
|
||||||
|
|
||||||
go hp.s.Serve(listener)
|
go func() {
|
||||||
|
_ = hp.s.Serve(listener)
|
||||||
|
}()
|
||||||
return hp, nil
|
return hp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +88,7 @@ func (hp *HTTPProxy) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBuf
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hp.l.PutConn(sc)
|
_ = hp.l.PutConn(sc)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hp *HTTPProxy) Close() error {
|
func (hp *HTTPProxy) Close() error {
|
||||||
@ -153,7 +154,7 @@ func (hp *HTTPProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
|
|||||||
client.Close()
|
client.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
client.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
_, _ = client.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||||
|
|
||||||
go frpIo.Join(remote, client)
|
go frpIo.Join(remote, client)
|
||||||
}
|
}
|
||||||
@ -188,7 +189,10 @@ func (hp *HTTPProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser)
|
|||||||
defer rwc.Close()
|
defer rwc.Close()
|
||||||
if ok := hp.Auth(req); !ok {
|
if ok := hp.Auth(req); !ok {
|
||||||
res := getBadResponse()
|
res := getBadResponse()
|
||||||
res.Write(rwc)
|
_ = res.Write(rwc)
|
||||||
|
if res.Body != nil {
|
||||||
|
res.Body.Close()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,10 +204,10 @@ func (hp *HTTPProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser)
|
|||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 1,
|
ProtoMinor: 1,
|
||||||
}
|
}
|
||||||
res.Write(rwc)
|
_ = res.Write(rwc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
_, _ = rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||||
|
|
||||||
frpIo.Join(remote, rwc)
|
frpIo.Join(remote, rwc)
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,9 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
|
|||||||
}
|
}
|
||||||
ln := tls.NewListener(listener, tlsConfig)
|
ln := tls.NewListener(listener, tlsConfig)
|
||||||
|
|
||||||
go p.s.Serve(ln)
|
go func() {
|
||||||
|
_ = p.s.Serve(ln)
|
||||||
|
}()
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +124,7 @@ func (p *HTTPS2HTTPPlugin) genTLSConfig() (*tls.Config, error) {
|
|||||||
|
|
||||||
func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||||
p.l.PutConn(wrapConn)
|
_ = p.l.PutConn(wrapConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTPS2HTTPPlugin) Name() string {
|
func (p *HTTPS2HTTPPlugin) Name() string {
|
||||||
|
@ -111,7 +111,9 @@ func NewHTTPS2HTTPSPlugin(params map[string]string) (Plugin, error) {
|
|||||||
}
|
}
|
||||||
ln := tls.NewListener(listener, tlsConfig)
|
ln := tls.NewListener(listener, tlsConfig)
|
||||||
|
|
||||||
go p.s.Serve(ln)
|
go func() {
|
||||||
|
_ = p.s.Serve(ln)
|
||||||
|
}()
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +129,7 @@ func (p *HTTPS2HTTPSPlugin) genTLSConfig() (*tls.Config, error) {
|
|||||||
|
|
||||||
func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||||
p.l.PutConn(wrapConn)
|
_ = p.l.PutConn(wrapConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTPS2HTTPSPlugin) Name() string {
|
func (p *HTTPS2HTTPSPlugin) Name() string {
|
||||||
|
@ -19,9 +19,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
|
||||||
|
|
||||||
gosocks5 "github.com/armon/go-socks5"
|
gosocks5 "github.com/armon/go-socks5"
|
||||||
|
|
||||||
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
const PluginSocks5 = "socks5"
|
const PluginSocks5 = "socks5"
|
||||||
@ -32,9 +32,6 @@ func init() {
|
|||||||
|
|
||||||
type Socks5Plugin struct {
|
type Socks5Plugin struct {
|
||||||
Server *gosocks5.Server
|
Server *gosocks5.Server
|
||||||
|
|
||||||
user string
|
|
||||||
passwd string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
|
func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
|
||||||
@ -56,7 +53,7 @@ func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
|
|||||||
func (sp *Socks5Plugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
func (sp *Socks5Plugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||||
sp.Server.ServeConn(wrapConn)
|
_ = sp.Server.ServeConn(wrapConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sp *Socks5Plugin) Name() string {
|
func (sp *Socks5Plugin) Name() string {
|
||||||
|
@ -19,9 +19,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
const PluginStaticFile = "static_file"
|
const PluginStaticFile = "static_file"
|
||||||
@ -69,13 +69,15 @@ func NewStaticFilePlugin(params map[string]string) (Plugin, error) {
|
|||||||
sp.s = &http.Server{
|
sp.s = &http.Server{
|
||||||
Handler: router,
|
Handler: router,
|
||||||
}
|
}
|
||||||
go sp.s.Serve(listener)
|
go func() {
|
||||||
|
_ = sp.s.Serve(listener)
|
||||||
|
}()
|
||||||
return sp, nil
|
return sp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sp *StaticFilePlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
func (sp *StaticFilePlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||||
sp.l.PutConn(wrapConn)
|
_ = sp.l.PutConn(wrapConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sp *StaticFilePlugin) Name() string {
|
func (sp *StaticFilePlugin) Name() string {
|
||||||
|
@ -57,7 +57,9 @@ func (uds *UnixDomainSocketPlugin) Handle(conn io.ReadWriteCloser, realConn net.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(extraBufToLocal) > 0 {
|
if len(extraBufToLocal) > 0 {
|
||||||
localConn.Write(extraBufToLocal)
|
if _, err := localConn.Write(extraBufToLocal); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frpIo.Join(localConn, conn)
|
frpIo.Join(localConn, conn)
|
||||||
|
@ -43,12 +43,12 @@ type httpPlugin struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPPluginOptions(options HTTPPluginOptions) Plugin {
|
func NewHTTPPluginOptions(options HTTPPluginOptions) Plugin {
|
||||||
var url = fmt.Sprintf("%s%s", options.Addr, options.Path)
|
url := fmt.Sprintf("%s%s", options.Addr, options.Path)
|
||||||
|
|
||||||
var client *http.Client
|
var client *http.Client
|
||||||
if strings.HasPrefix(url, "https://") {
|
if strings.HasPrefix(url, "https://") {
|
||||||
tr := &http.Transport{
|
tr := &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: options.TLSVerify == false},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: !options.TLSVerify},
|
||||||
}
|
}
|
||||||
client = &http.Client{Transport: tr}
|
client = &http.Client{Transport: tr}
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,9 +154,8 @@ func (m *Manager) CloseProxy(content *CloseProxyContent) error {
|
|||||||
|
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
return fmt.Errorf("send CloseProxy request to plugin errors: %s", strings.Join(errs, "; "))
|
return fmt.Errorf("send CloseProxy request to plugin errors: %s", strings.Join(errs, "; "))
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
|
func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
|
||||||
|
@ -20,10 +20,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
"github.com/fatedier/golib/errors"
|
||||||
"github.com/fatedier/golib/pool"
|
"github.com/fatedier/golib/pool"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewUDPPacket(buf []byte, laddr, raddr *net.UDPAddr) *msg.UDPPacket {
|
func NewUDPPacket(buf []byte, laddr, raddr *net.UDPAddr) *msg.UDPPacket {
|
||||||
@ -47,7 +47,7 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UDPPacket, sendCh
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
udpConn.WriteToUDP(buf, udpMsg.RemoteAddr)
|
_, _ = udpConn.WriteToUDP(buf, udpMsg.RemoteAddr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -70,9 +70,7 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UDPPacket, sendCh
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<- msg.Message, bufSize int) {
|
func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<- msg.Message, bufSize int) {
|
||||||
var (
|
var mu sync.RWMutex
|
||||||
mu sync.RWMutex
|
|
||||||
)
|
|
||||||
udpConnMap := make(map[string]*net.UDPConn)
|
udpConnMap := make(map[string]*net.UDPConn)
|
||||||
|
|
||||||
// read from dstAddr and write to sendCh
|
// read from dstAddr and write to sendCh
|
||||||
@ -87,7 +85,7 @@ func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<-
|
|||||||
|
|
||||||
buf := pool.GetBuf(bufSize)
|
buf := pool.GetBuf(bufSize)
|
||||||
for {
|
for {
|
||||||
udpConn.SetReadDeadline(time.Now().Add(30 * time.Second))
|
_ = udpConn.SetReadDeadline(time.Now().Add(30 * time.Second))
|
||||||
n, _, err := udpConn.ReadFromUDP(buf)
|
n, _, err := udpConn.ReadFromUDP(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -19,7 +19,7 @@ func newCustomTLSKeyPair(certfile, keyfile string) (*tls.Certificate, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newRandomTLSKeyPair() *tls.Certificate {
|
func newRandomTLSKeyPair() *tls.Certificate {
|
||||||
key, err := rsa.GenerateKey(rand.Reader, 1024)
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ func newCertPool(caPath string) (*x509.CertPool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
|
func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
|
||||||
var base = &tls.Config{}
|
base := &tls.Config{}
|
||||||
|
|
||||||
if certPath == "" || keyPath == "" {
|
if certPath == "" || keyPath == "" {
|
||||||
// server will generate tls conf by itself
|
// server will generate tls conf by itself
|
||||||
@ -87,7 +87,7 @@ func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewClientTLSConfig(certPath, keyPath, caPath, serverName string) (*tls.Config, error) {
|
func NewClientTLSConfig(certPath, keyPath, caPath, serverName string) (*tls.Config, error) {
|
||||||
var base = &tls.Config{}
|
base := &tls.Config{}
|
||||||
|
|
||||||
if certPath == "" || keyPath == "" {
|
if certPath == "" || keyPath == "" {
|
||||||
// client will not generate tls conf by itself
|
// client will not generate tls conf by itself
|
||||||
|
@ -40,19 +40,19 @@ func SetLogFile(logWay string, logFile string, maxdays int64, disableLogColor bo
|
|||||||
if logWay == "console" {
|
if logWay == "console" {
|
||||||
params := ""
|
params := ""
|
||||||
if disableLogColor {
|
if disableLogColor {
|
||||||
params = fmt.Sprintf(`{"color": false}`)
|
params = `{"color": false}`
|
||||||
}
|
}
|
||||||
Log.SetLogger("console", params)
|
_ = Log.SetLogger("console", params)
|
||||||
} else {
|
} else {
|
||||||
params := fmt.Sprintf(`{"filename": "%s", "maxdays": %d}`, logFile, maxdays)
|
params := fmt.Sprintf(`{"filename": "%s", "maxdays": %d}`, logFile, maxdays)
|
||||||
Log.SetLogger("file", params)
|
_ = Log.SetLogger("file", params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLogLevel set log level, default is warning
|
// SetLogLevel set log level, default is warning
|
||||||
// value: error, warning, info, debug, trace
|
// value: error, warning, info, debug, trace
|
||||||
func SetLogLevel(logLevel string) {
|
func SetLogLevel(logLevel string) {
|
||||||
level := 4 // warning
|
var level int
|
||||||
switch logLevel {
|
switch logLevel {
|
||||||
case "error":
|
case "error":
|
||||||
level = 3
|
level = 3
|
||||||
@ -65,7 +65,7 @@ func SetLogLevel(logLevel string) {
|
|||||||
case "trace":
|
case "trace":
|
||||||
level = 8
|
level = 8
|
||||||
default:
|
default:
|
||||||
level = 4
|
level = 4 // warning
|
||||||
}
|
}
|
||||||
Log.SetLevel(level)
|
Log.SetLevel(level)
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@ func ListenKcp(address string) (l *KCPListener, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return l, err
|
return l, err
|
||||||
}
|
}
|
||||||
listener.SetReadBuffer(4194304)
|
_ = listener.SetReadBuffer(4194304)
|
||||||
listener.SetWriteBuffer(4194304)
|
_ = listener.SetWriteBuffer(4194304)
|
||||||
|
|
||||||
l = &KCPListener{
|
l = &KCPListener{
|
||||||
listener: listener,
|
listener: listener,
|
||||||
|
@ -23,32 +23,30 @@ import (
|
|||||||
gnet "github.com/fatedier/golib/net"
|
gnet "github.com/fatedier/golib/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var FRPTLSHeadByte = 0x17
|
||||||
FRPTLSHeadByte = 0x17
|
|
||||||
)
|
|
||||||
|
|
||||||
func CheckAndEnableTLSServerConnWithTimeout(
|
func CheckAndEnableTLSServerConnWithTimeout(
|
||||||
c net.Conn, tlsConfig *tls.Config, tlsOnly bool, timeout time.Duration,
|
c net.Conn, tlsConfig *tls.Config, tlsOnly bool, timeout time.Duration,
|
||||||
) (out net.Conn, isTLS bool, custom bool, err error) {
|
) (out net.Conn, isTLS bool, custom bool, err error) {
|
||||||
|
|
||||||
sc, r := gnet.NewSharedConnSize(c, 2)
|
sc, r := gnet.NewSharedConnSize(c, 2)
|
||||||
buf := make([]byte, 1)
|
buf := make([]byte, 1)
|
||||||
var n int
|
var n int
|
||||||
c.SetReadDeadline(time.Now().Add(timeout))
|
_ = c.SetReadDeadline(time.Now().Add(timeout))
|
||||||
n, err = r.Read(buf)
|
n, err = r.Read(buf)
|
||||||
c.SetReadDeadline(time.Time{})
|
_ = c.SetReadDeadline(time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if n == 1 && int(buf[0]) == FRPTLSHeadByte {
|
switch {
|
||||||
|
case n == 1 && int(buf[0]) == FRPTLSHeadByte:
|
||||||
out = tls.Server(c, tlsConfig)
|
out = tls.Server(c, tlsConfig)
|
||||||
isTLS = true
|
isTLS = true
|
||||||
custom = true
|
custom = true
|
||||||
} else if n == 1 && int(buf[0]) == 0x16 {
|
case n == 1 && int(buf[0]) == 0x16:
|
||||||
out = tls.Server(sc, tlsConfig)
|
out = tls.Server(sc, tlsConfig)
|
||||||
isTLS = true
|
isTLS = true
|
||||||
} else {
|
default:
|
||||||
if tlsOnly {
|
if tlsOnly {
|
||||||
err = fmt.Errorf("non-TLS connection received on a TlsOnly server")
|
err = fmt.Errorf("non-TLS connection received on a TlsOnly server")
|
||||||
return
|
return
|
||||||
|
@ -55,7 +55,7 @@ func NewFakeUDPConn(l *UDPListener, laddr, raddr net.Addr) *FakeUDPConn {
|
|||||||
for {
|
for {
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
fc.mu.RLock()
|
fc.mu.RLock()
|
||||||
if time.Now().Sub(fc.lastActive) > 10*time.Second {
|
if time.Since(fc.lastActive) > 10*time.Second {
|
||||||
fc.mu.RUnlock()
|
fc.mu.RUnlock()
|
||||||
fc.Close()
|
fc.Close()
|
||||||
break
|
break
|
||||||
@ -68,8 +68,7 @@ func NewFakeUDPConn(l *UDPListener, laddr, raddr net.Addr) *FakeUDPConn {
|
|||||||
|
|
||||||
func (c *FakeUDPConn) putPacket(content []byte) {
|
func (c *FakeUDPConn) putPacket(content []byte) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
_ = recover()
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@ -109,7 +108,7 @@ func (c *FakeUDPConn) Write(b []byte) (n int, err error) {
|
|||||||
LocalAddr: c.localAddr,
|
LocalAddr: c.localAddr,
|
||||||
RemoteAddr: c.remoteAddr,
|
RemoteAddr: c.remoteAddr,
|
||||||
}
|
}
|
||||||
c.l.writeUDPPacket(packet)
|
_ = c.l.writeUDPPacket(packet)
|
||||||
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
c.lastActive = time.Now()
|
c.lastActive = time.Now()
|
||||||
@ -208,7 +207,7 @@ func ListenUDP(bindAddr string, bindPort int) (l *UDPListener, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if addr, ok := packet.RemoteAddr.(*net.UDPAddr); ok {
|
if addr, ok := packet.RemoteAddr.(*net.UDPAddr); ok {
|
||||||
readConn.WriteToUDP(packet.Buf, addr)
|
_, _ = readConn.WriteToUDP(packet.Buf, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -9,9 +9,7 @@ import (
|
|||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrWebsocketListenerClosed = errors.New("websocket listener closed")
|
||||||
ErrWebsocketListenerClosed = errors.New("websocket listener closed")
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FrpWebsocketPath = "/~!frp"
|
FrpWebsocketPath = "/~!frp"
|
||||||
@ -21,8 +19,7 @@ type WebsocketListener struct {
|
|||||||
ln net.Listener
|
ln net.Listener
|
||||||
acceptCh chan net.Conn
|
acceptCh chan net.Conn
|
||||||
|
|
||||||
server *http.Server
|
server *http.Server
|
||||||
httpMutex *http.ServeMux
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWebsocketListener to handle websocket connections
|
// NewWebsocketListener to handle websocket connections
|
||||||
@ -47,7 +44,9 @@ func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
|
|||||||
Handler: muxer,
|
Handler: muxer,
|
||||||
}
|
}
|
||||||
|
|
||||||
go wl.server.Serve(ln)
|
go func() {
|
||||||
|
_ = wl.server.Serve(ln)
|
||||||
|
}()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +22,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
gnet "github.com/fatedier/golib/net"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
"github.com/fatedier/frp/pkg/util/vhost"
|
"github.com/fatedier/frp/pkg/util/vhost"
|
||||||
gnet "github.com/fatedier/golib/net"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type HTTPConnectTCPMuxer struct {
|
type HTTPConnectTCPMuxer struct {
|
||||||
@ -66,7 +67,11 @@ func (muxer *HTTPConnectTCPMuxer) sendConnectResponse(c net.Conn, reqInfo map[st
|
|||||||
if muxer.passthrough {
|
if muxer.passthrough {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return util.OkResponse().Write(c)
|
res := util.OkResponse()
|
||||||
|
if res.Body != nil {
|
||||||
|
defer res.Body.Close()
|
||||||
|
}
|
||||||
|
return res.Write(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (muxer *HTTPConnectTCPMuxer) getHostFromHTTPConnect(c net.Conn) (net.Conn, map[string]string, error) {
|
func (muxer *HTTPConnectTCPMuxer) getHostFromHTTPConnect(c net.Conn) (net.Conn, map[string]string, error) {
|
||||||
@ -82,11 +87,15 @@ func (muxer *HTTPConnectTCPMuxer) getHostFromHTTPConnect(c net.Conn) (net.Conn,
|
|||||||
reqInfoMap["Scheme"] = "tcp"
|
reqInfoMap["Scheme"] = "tcp"
|
||||||
reqInfoMap["HTTPUser"] = httpUser
|
reqInfoMap["HTTPUser"] = httpUser
|
||||||
|
|
||||||
var outConn net.Conn = c
|
outConn := c
|
||||||
if muxer.passthrough {
|
if muxer.passthrough {
|
||||||
outConn = sc
|
outConn = sc
|
||||||
if muxer.authRequired && httpUser == "" {
|
if muxer.authRequired && httpUser == "" {
|
||||||
util.ProxyUnauthorizedResponse().Write(c)
|
resp := util.ProxyUnauthorizedResponse()
|
||||||
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
_ = resp.Write(c)
|
||||||
outConn = c
|
outConn = c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,10 +60,8 @@ func CanonicalHost(host string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(host, ".") {
|
// Strip trailing dot from fully qualified domain names.
|
||||||
// Strip trailing dot from fully qualified domain names.
|
host = strings.TrimSuffix(host, ".")
|
||||||
host = host[:len(host)-1]
|
|
||||||
}
|
|
||||||
return host, nil
|
return host, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ func RandIDWithLen(idLen int) (id string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetAuthKey(token string, timestamp int64) (key string) {
|
func GetAuthKey(token string, timestamp int64) (key string) {
|
||||||
token = token + fmt.Sprintf("%d", timestamp)
|
token += fmt.Sprintf("%d", timestamp)
|
||||||
md5Ctx := md5.New()
|
md5Ctx := md5.New()
|
||||||
md5Ctx.Write([]byte(token))
|
md5Ctx.Write([]byte(token))
|
||||||
data := md5Ctx.Sum(nil)
|
data := md5Ctx.Sum(nil)
|
||||||
@ -70,7 +70,8 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
|||||||
numArray := strings.Split(numRangeStr, "-")
|
numArray := strings.Split(numRangeStr, "-")
|
||||||
// length: only 1 or 2 is correct
|
// length: only 1 or 2 is correct
|
||||||
rangeType := len(numArray)
|
rangeType := len(numArray)
|
||||||
if rangeType == 1 {
|
switch rangeType {
|
||||||
|
case 1:
|
||||||
// single number
|
// single number
|
||||||
singleNum, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
singleNum, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
||||||
if errRet != nil {
|
if errRet != nil {
|
||||||
@ -78,7 +79,7 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
numbers = append(numbers, singleNum)
|
numbers = append(numbers, singleNum)
|
||||||
} else if rangeType == 2 {
|
case 2:
|
||||||
// range numbers
|
// range numbers
|
||||||
min, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
min, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
||||||
if errRet != nil {
|
if errRet != nil {
|
||||||
@ -97,7 +98,7 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
|||||||
for i := min; i <= max; i++ {
|
for i := min; i <= max; i++ {
|
||||||
numbers = append(numbers, i)
|
numbers = append(numbers, i)
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
err = fmt.Errorf("range number is invalid")
|
err = fmt.Errorf("range number is invalid")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version string = "0.44.0"
|
var version = "0.45.0"
|
||||||
|
|
||||||
func Full() string {
|
func Full() string {
|
||||||
return version
|
return version
|
||||||
|
@ -23,27 +23,26 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
frpIo "github.com/fatedier/golib/io"
|
||||||
|
"github.com/fatedier/golib/pool"
|
||||||
|
|
||||||
frpLog "github.com/fatedier/frp/pkg/util/log"
|
frpLog "github.com/fatedier/frp/pkg/util/log"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
frpIo "github.com/fatedier/golib/io"
|
|
||||||
|
|
||||||
"github.com/fatedier/golib/pool"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrNoRouteFound = errors.New("no route found")
|
||||||
ErrNoRouteFound = errors.New("no route found")
|
|
||||||
)
|
|
||||||
|
|
||||||
type HTTPReverseProxyOptions struct {
|
type HTTPReverseProxyOptions struct {
|
||||||
ResponseHeaderTimeoutS int64
|
ResponseHeaderTimeoutS int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPReverseProxy struct {
|
type HTTPReverseProxy struct {
|
||||||
proxy *ReverseProxy
|
proxy *httputil.ReverseProxy
|
||||||
vhostRouter *Routers
|
vhostRouter *Routers
|
||||||
|
|
||||||
responseHeaderTimeout time.Duration
|
responseHeaderTimeout time.Duration
|
||||||
@ -57,23 +56,32 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
|||||||
responseHeaderTimeout: time.Duration(option.ResponseHeaderTimeoutS) * time.Second,
|
responseHeaderTimeout: time.Duration(option.ResponseHeaderTimeoutS) * time.Second,
|
||||||
vhostRouter: vhostRouter,
|
vhostRouter: vhostRouter,
|
||||||
}
|
}
|
||||||
proxy := &ReverseProxy{
|
proxy := &httputil.ReverseProxy{
|
||||||
// Modify incoming requests by route policies.
|
// Modify incoming requests by route policies.
|
||||||
Director: func(req *http.Request) {
|
Director: func(req *http.Request) {
|
||||||
req.URL.Scheme = "http"
|
req.URL.Scheme = "http"
|
||||||
url := req.Context().Value(RouteInfoURL).(string)
|
reqRouteInfo := req.Context().Value(RouteInfoKey).(*RequestRouteInfo)
|
||||||
routeByHTTPUser := req.Context().Value(RouteInfoHTTPUser).(string)
|
oldHost, _ := util.CanonicalHost(reqRouteInfo.Host)
|
||||||
oldHost, _ := util.CanonicalHost(req.Context().Value(RouteInfoHost).(string))
|
|
||||||
rc := rp.GetRouteConfig(oldHost, url, routeByHTTPUser)
|
rc := rp.GetRouteConfig(oldHost, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
||||||
if rc != nil {
|
if rc != nil {
|
||||||
if rc.RewriteHost != "" {
|
if rc.RewriteHost != "" {
|
||||||
req.Host = rc.RewriteHost
|
req.Host = rc.RewriteHost
|
||||||
}
|
}
|
||||||
// Set {domain}.{location}.{routeByHTTPUser} as URL host here to let http transport reuse connections.
|
|
||||||
// TODO(fatedier): use proxy name instead?
|
var endpoint string
|
||||||
|
if rc.ChooseEndpointFn != nil {
|
||||||
|
// ignore error here, it will use CreateConnFn instead later
|
||||||
|
endpoint, _ = rc.ChooseEndpointFn()
|
||||||
|
reqRouteInfo.Endpoint = endpoint
|
||||||
|
frpLog.Trace("choose endpoint name [%s] for http request host [%s] path [%s] httpuser [%s]",
|
||||||
|
endpoint, oldHost, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
||||||
|
}
|
||||||
|
// Set {domain}.{location}.{routeByHTTPUser}.{endpoint} as URL host here to let http transport reuse connections.
|
||||||
req.URL.Host = rc.Domain + "." +
|
req.URL.Host = rc.Domain + "." +
|
||||||
base64.StdEncoding.EncodeToString([]byte(rc.Location)) + "." +
|
base64.StdEncoding.EncodeToString([]byte(rc.Location)) + "." +
|
||||||
base64.StdEncoding.EncodeToString([]byte(rc.RouteByHTTPUser))
|
base64.StdEncoding.EncodeToString([]byte(rc.RouteByHTTPUser)) + "." +
|
||||||
|
base64.StdEncoding.EncodeToString([]byte(endpoint))
|
||||||
|
|
||||||
for k, v := range rc.Headers {
|
for k, v := range rc.Headers {
|
||||||
req.Header.Set(k, v)
|
req.Header.Set(k, v)
|
||||||
@ -81,18 +89,14 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
|||||||
} else {
|
} else {
|
||||||
req.URL.Host = req.Host
|
req.URL.Host = req.Host
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
// Create a connection to one proxy routed by route policy.
|
// Create a connection to one proxy routed by route policy.
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
ResponseHeaderTimeout: rp.responseHeaderTimeout,
|
ResponseHeaderTimeout: rp.responseHeaderTimeout,
|
||||||
IdleConnTimeout: 60 * time.Second,
|
IdleConnTimeout: 60 * time.Second,
|
||||||
|
MaxIdleConnsPerHost: 5,
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
url := ctx.Value(RouteInfoURL).(string)
|
return rp.CreateConnection(ctx.Value(RouteInfoKey).(*RequestRouteInfo), true)
|
||||||
host, _ := util.CanonicalHost(ctx.Value(RouteInfoHost).(string))
|
|
||||||
routerByHTTPUser := ctx.Value(RouteInfoHTTPUser).(string)
|
|
||||||
remote := ctx.Value(RouteInfoRemote).(string)
|
|
||||||
return rp.CreateConnection(host, url, routerByHTTPUser, remote)
|
|
||||||
},
|
},
|
||||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||||
// Use proxy mode if there is host in HTTP first request line.
|
// Use proxy mode if there is host in HTTP first request line.
|
||||||
@ -102,7 +106,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
|||||||
// Normal:
|
// Normal:
|
||||||
// GET / HTTP/1.1
|
// GET / HTTP/1.1
|
||||||
// Host: example.com
|
// Host: example.com
|
||||||
urlHost := req.Context().Value(RouteInfoURLHost).(string)
|
urlHost := req.Context().Value(RouteInfoKey).(*RequestRouteInfo).URLHost
|
||||||
if urlHost != "" {
|
if urlHost != "" {
|
||||||
return req.URL, nil
|
return req.URL, nil
|
||||||
}
|
}
|
||||||
@ -114,7 +118,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
|||||||
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
|
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
|
||||||
frpLog.Warn("do http proxy request [host: %s] error: %v", req.Host, err)
|
frpLog.Warn("do http proxy request [host: %s] error: %v", req.Host, err)
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
rw.WriteHeader(http.StatusNotFound)
|
||||||
rw.Write(getNotFoundPageContent())
|
_, _ = rw.Write(getNotFoundPageContent())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
rp.proxy = proxy
|
rp.proxy = proxy
|
||||||
@ -145,14 +149,6 @@ func (rp *HTTPReverseProxy) GetRouteConfig(domain, location, routeByHTTPUser str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rp *HTTPReverseProxy) GetRealHost(domain, location, routeByHTTPUser string) (host string) {
|
|
||||||
vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
|
|
||||||
if ok {
|
|
||||||
host = vr.payload.(*RouteConfig).RewriteHost
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rp *HTTPReverseProxy) GetHeaders(domain, location, routeByHTTPUser string) (headers map[string]string) {
|
func (rp *HTTPReverseProxy) GetHeaders(domain, location, routeByHTTPUser string) (headers map[string]string) {
|
||||||
vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
|
vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
|
||||||
if ok {
|
if ok {
|
||||||
@ -162,15 +158,22 @@ func (rp *HTTPReverseProxy) GetHeaders(domain, location, routeByHTTPUser string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateConnection create a new connection by route config
|
// CreateConnection create a new connection by route config
|
||||||
func (rp *HTTPReverseProxy) CreateConnection(domain, location, routeByHTTPUser string, remoteAddr string) (net.Conn, error) {
|
func (rp *HTTPReverseProxy) CreateConnection(reqRouteInfo *RequestRouteInfo, byEndpoint bool) (net.Conn, error) {
|
||||||
vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
|
host, _ := util.CanonicalHost(reqRouteInfo.Host)
|
||||||
|
vr, ok := rp.getVhost(host, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
||||||
if ok {
|
if ok {
|
||||||
|
if byEndpoint {
|
||||||
|
fn := vr.payload.(*RouteConfig).CreateConnByEndpointFn
|
||||||
|
if fn != nil {
|
||||||
|
return fn(reqRouteInfo.Endpoint, reqRouteInfo.RemoteAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
fn := vr.payload.(*RouteConfig).CreateConnFn
|
fn := vr.payload.(*RouteConfig).CreateConnFn
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
return fn(remoteAddr)
|
return fn(reqRouteInfo.RemoteAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%v: %s %s %s", ErrNoRouteFound, domain, location, routeByHTTPUser)
|
return nil, fmt.Errorf("%v: %s %s %s", ErrNoRouteFound, host, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rp *HTTPReverseProxy) CheckAuth(domain, location, routeByHTTPUser, user, passwd string) bool {
|
func (rp *HTTPReverseProxy) CheckAuth(domain, location, routeByHTTPUser, user, passwd string) bool {
|
||||||
@ -246,27 +249,35 @@ func (rp *HTTPReverseProxy) connectHandler(rw http.ResponseWriter, req *http.Req
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
url := req.Context().Value(RouteInfoURL).(string)
|
remote, err := rp.CreateConnection(req.Context().Value(RouteInfoKey).(*RequestRouteInfo), false)
|
||||||
routeByHTTPUser := req.Context().Value(RouteInfoHTTPUser).(string)
|
|
||||||
domain, _ := util.CanonicalHost(req.Context().Value(RouteInfoHost).(string))
|
|
||||||
remoteAddr := req.Context().Value(RouteInfoRemote).(string)
|
|
||||||
|
|
||||||
remote, err := rp.CreateConnection(domain, url, routeByHTTPUser, remoteAddr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(rw, "Failed", http.StatusBadRequest)
|
_ = notFoundResponse().Write(client)
|
||||||
client.Close()
|
client.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.Write(remote)
|
_ = req.Write(remote)
|
||||||
go frpIo.Join(remote, client)
|
go frpIo.Join(remote, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Request {
|
func parseBasicAuth(auth string) (username, password string, ok bool) {
|
||||||
newctx := req.Context()
|
const prefix = "Basic "
|
||||||
newctx = context.WithValue(newctx, RouteInfoURL, req.URL.Path)
|
// Case insensitive prefix match. See Issue 22736.
|
||||||
newctx = context.WithValue(newctx, RouteInfoHost, req.Host)
|
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
|
||||||
newctx = context.WithValue(newctx, RouteInfoURLHost, req.URL.Host)
|
return
|
||||||
|
}
|
||||||
|
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cs := string(c)
|
||||||
|
s := strings.IndexByte(cs, ':')
|
||||||
|
if s < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return cs[:s], cs[s+1:], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Request {
|
||||||
user := ""
|
user := ""
|
||||||
// If url host isn't empty, it's a proxy request. Get http user from Proxy-Authorization header.
|
// If url host isn't empty, it's a proxy request. Get http user from Proxy-Authorization header.
|
||||||
if req.URL.Host != "" {
|
if req.URL.Host != "" {
|
||||||
@ -278,8 +289,16 @@ func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Requ
|
|||||||
if user == "" {
|
if user == "" {
|
||||||
user, _, _ = req.BasicAuth()
|
user, _, _ = req.BasicAuth()
|
||||||
}
|
}
|
||||||
newctx = context.WithValue(newctx, RouteInfoHTTPUser, user)
|
|
||||||
newctx = context.WithValue(newctx, RouteInfoRemote, req.RemoteAddr)
|
reqRouteInfo := &RequestRouteInfo{
|
||||||
|
URL: req.URL.Path,
|
||||||
|
Host: req.Host,
|
||||||
|
HTTPUser: user,
|
||||||
|
RemoteAddr: req.RemoteAddr,
|
||||||
|
URLHost: req.URL.Host,
|
||||||
|
}
|
||||||
|
newctx := req.Context()
|
||||||
|
newctx = context.WithValue(newctx, RouteInfoKey, reqRouteInfo)
|
||||||
return req.Clone(newctx)
|
return req.Clone(newctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/util/version"
|
"github.com/fatedier/frp/pkg/util/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var NotFoundPagePath = ""
|
||||||
NotFoundPagePath = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NotFound = `<!DOCTYPE html>
|
NotFound = `<!DOCTYPE html>
|
||||||
@ -74,14 +72,16 @@ func notFoundResponse() *http.Response {
|
|||||||
header.Set("server", "frp/"+version.Full())
|
header.Set("server", "frp/"+version.Full())
|
||||||
header.Set("Content-Type", "text/html")
|
header.Set("Content-Type", "text/html")
|
||||||
|
|
||||||
|
content := getNotFoundPageContent()
|
||||||
res := &http.Response{
|
res := &http.Response{
|
||||||
Status: "Not Found",
|
Status: "Not Found",
|
||||||
StatusCode: 404,
|
StatusCode: 404,
|
||||||
Proto: "HTTP/1.0",
|
Proto: "HTTP/1.1",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 1,
|
||||||
Header: header,
|
Header: header,
|
||||||
Body: io.NopCloser(bytes.NewReader(getNotFoundPageContent())),
|
Body: io.NopCloser(bytes.NewReader(content)),
|
||||||
|
ContentLength: int64(len(content)),
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -1,636 +0,0 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// HTTP reverse proxy handler
|
|
||||||
|
|
||||||
package vhost
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/textproto"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/http/httpguts"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ReverseProxy is an HTTP Handler that takes an incoming request and
|
|
||||||
// sends it to another server, proxying the response back to the
|
|
||||||
// client.
|
|
||||||
//
|
|
||||||
// ReverseProxy by default sets the client IP as the value of the
|
|
||||||
// X-Forwarded-For header.
|
|
||||||
//
|
|
||||||
// If an X-Forwarded-For header already exists, the client IP is
|
|
||||||
// appended to the existing values. As a special case, if the header
|
|
||||||
// exists in the Request.Header map but has a nil value (such as when
|
|
||||||
// set by the Director func), the X-Forwarded-For header is
|
|
||||||
// not modified.
|
|
||||||
//
|
|
||||||
// To prevent IP spoofing, be sure to delete any pre-existing
|
|
||||||
// X-Forwarded-For header coming from the client or
|
|
||||||
// an untrusted proxy.
|
|
||||||
type ReverseProxy struct {
|
|
||||||
// Director must be a function which modifies
|
|
||||||
// the request into a new request to be sent
|
|
||||||
// using Transport. Its response is then copied
|
|
||||||
// back to the original client unmodified.
|
|
||||||
// Director must not access the provided Request
|
|
||||||
// after returning.
|
|
||||||
Director func(*http.Request)
|
|
||||||
|
|
||||||
// The transport used to perform proxy requests.
|
|
||||||
// If nil, http.DefaultTransport is used.
|
|
||||||
Transport http.RoundTripper
|
|
||||||
|
|
||||||
// FlushInterval specifies the flush interval
|
|
||||||
// to flush to the client while copying the
|
|
||||||
// response body.
|
|
||||||
// If zero, no periodic flushing is done.
|
|
||||||
// A negative value means to flush immediately
|
|
||||||
// after each write to the client.
|
|
||||||
// The FlushInterval is ignored when ReverseProxy
|
|
||||||
// recognizes a response as a streaming response, or
|
|
||||||
// if its ContentLength is -1; for such responses, writes
|
|
||||||
// are flushed to the client immediately.
|
|
||||||
FlushInterval time.Duration
|
|
||||||
|
|
||||||
// ErrorLog specifies an optional logger for errors
|
|
||||||
// that occur when attempting to proxy the request.
|
|
||||||
// If nil, logging is done via the log package's standard logger.
|
|
||||||
ErrorLog *log.Logger
|
|
||||||
|
|
||||||
// BufferPool optionally specifies a buffer pool to
|
|
||||||
// get byte slices for use by io.CopyBuffer when
|
|
||||||
// copying HTTP response bodies.
|
|
||||||
BufferPool BufferPool
|
|
||||||
|
|
||||||
// ModifyResponse is an optional function that modifies the
|
|
||||||
// Response from the backend. It is called if the backend
|
|
||||||
// returns a response at all, with any HTTP status code.
|
|
||||||
// If the backend is unreachable, the optional ErrorHandler is
|
|
||||||
// called without any call to ModifyResponse.
|
|
||||||
//
|
|
||||||
// If ModifyResponse returns an error, ErrorHandler is called
|
|
||||||
// with its error value. If ErrorHandler is nil, its default
|
|
||||||
// implementation is used.
|
|
||||||
ModifyResponse func(*http.Response) error
|
|
||||||
|
|
||||||
// ErrorHandler is an optional function that handles errors
|
|
||||||
// reaching the backend or errors from ModifyResponse.
|
|
||||||
//
|
|
||||||
// If nil, the default is to log the provided error and return
|
|
||||||
// a 502 Status Bad Gateway response.
|
|
||||||
ErrorHandler func(http.ResponseWriter, *http.Request, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A BufferPool is an interface for getting and returning temporary
|
|
||||||
// byte slices for use by io.CopyBuffer.
|
|
||||||
type BufferPool interface {
|
|
||||||
Get() []byte
|
|
||||||
Put([]byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
func singleJoiningSlash(a, b string) string {
|
|
||||||
aslash := strings.HasSuffix(a, "/")
|
|
||||||
bslash := strings.HasPrefix(b, "/")
|
|
||||||
switch {
|
|
||||||
case aslash && bslash:
|
|
||||||
return a + b[1:]
|
|
||||||
case !aslash && !bslash:
|
|
||||||
return a + "/" + b
|
|
||||||
}
|
|
||||||
return a + b
|
|
||||||
}
|
|
||||||
|
|
||||||
func joinURLPath(a, b *url.URL) (path, rawpath string) {
|
|
||||||
if a.RawPath == "" && b.RawPath == "" {
|
|
||||||
return singleJoiningSlash(a.Path, b.Path), ""
|
|
||||||
}
|
|
||||||
// Same as singleJoiningSlash, but uses EscapedPath to determine
|
|
||||||
// whether a slash should be added
|
|
||||||
apath := a.EscapedPath()
|
|
||||||
bpath := b.EscapedPath()
|
|
||||||
|
|
||||||
aslash := strings.HasSuffix(apath, "/")
|
|
||||||
bslash := strings.HasPrefix(bpath, "/")
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case aslash && bslash:
|
|
||||||
return a.Path + b.Path[1:], apath + bpath[1:]
|
|
||||||
case !aslash && !bslash:
|
|
||||||
return a.Path + "/" + b.Path, apath + "/" + bpath
|
|
||||||
}
|
|
||||||
return a.Path + b.Path, apath + bpath
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSingleHostReverseProxy returns a new ReverseProxy that routes
|
|
||||||
// URLs to the scheme, host, and base path provided in target. If the
|
|
||||||
// target's path is "/base" and the incoming request was for "/dir",
|
|
||||||
// the target request will be for /base/dir.
|
|
||||||
// NewSingleHostReverseProxy does not rewrite the Host header.
|
|
||||||
// To rewrite Host headers, use ReverseProxy directly with a custom
|
|
||||||
// Director policy.
|
|
||||||
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
|
|
||||||
targetQuery := target.RawQuery
|
|
||||||
director := func(req *http.Request) {
|
|
||||||
req.URL.Scheme = target.Scheme
|
|
||||||
req.URL.Host = target.Host
|
|
||||||
req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL)
|
|
||||||
if targetQuery == "" || req.URL.RawQuery == "" {
|
|
||||||
req.URL.RawQuery = targetQuery + req.URL.RawQuery
|
|
||||||
} else {
|
|
||||||
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
|
|
||||||
}
|
|
||||||
if _, ok := req.Header["User-Agent"]; !ok {
|
|
||||||
// explicitly disable User-Agent so it's not set to default value
|
|
||||||
req.Header.Set("User-Agent", "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &ReverseProxy{Director: director}
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyHeader(dst, src http.Header) {
|
|
||||||
for k, vv := range src {
|
|
||||||
for _, v := range vv {
|
|
||||||
dst.Add(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hop-by-hop headers. These are removed when sent to the backend.
|
|
||||||
// As of RFC 7230, hop-by-hop headers are required to appear in the
|
|
||||||
// Connection header field. These are the headers defined by the
|
|
||||||
// obsoleted RFC 2616 (section 13.5.1) and are used for backward
|
|
||||||
// compatibility.
|
|
||||||
var hopHeaders = []string{
|
|
||||||
"Connection",
|
|
||||||
"Proxy-Connection", // non-standard but still sent by libcurl and rejected by e.g. google
|
|
||||||
"Keep-Alive",
|
|
||||||
"Proxy-Authenticate",
|
|
||||||
"Proxy-Authorization",
|
|
||||||
"Te", // canonicalized version of "TE"
|
|
||||||
"Trailer", // not Trailers per URL above; https://www.rfc-editor.org/errata_search.php?eid=4522
|
|
||||||
"Transfer-Encoding",
|
|
||||||
"Upgrade",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ReverseProxy) defaultErrorHandler(rw http.ResponseWriter, req *http.Request, err error) {
|
|
||||||
p.logf("http: proxy error: %v", err)
|
|
||||||
rw.WriteHeader(http.StatusBadGateway)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ReverseProxy) getErrorHandler() func(http.ResponseWriter, *http.Request, error) {
|
|
||||||
if p.ErrorHandler != nil {
|
|
||||||
return p.ErrorHandler
|
|
||||||
}
|
|
||||||
return p.defaultErrorHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
// modifyResponse conditionally runs the optional ModifyResponse hook
|
|
||||||
// and reports whether the request should proceed.
|
|
||||||
func (p *ReverseProxy) modifyResponse(rw http.ResponseWriter, res *http.Response, req *http.Request) bool {
|
|
||||||
if p.ModifyResponse == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if err := p.ModifyResponse(res); err != nil {
|
|
||||||
res.Body.Close()
|
|
||||||
p.getErrorHandler()(rw, req, err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseBasicAuth(auth string) (username, password string, ok bool) {
|
|
||||||
const prefix = "Basic "
|
|
||||||
// Case insensitive prefix match. See Issue 22736.
|
|
||||||
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cs := string(c)
|
|
||||||
s := strings.IndexByte(cs, ':')
|
|
||||||
if s < 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return cs[:s], cs[s+1:], true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
transport := p.Transport
|
|
||||||
if transport == nil {
|
|
||||||
transport = http.DefaultTransport
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := req.Context()
|
|
||||||
if cn, ok := rw.(http.CloseNotifier); ok {
|
|
||||||
var cancel context.CancelFunc
|
|
||||||
ctx, cancel = context.WithCancel(ctx)
|
|
||||||
defer cancel()
|
|
||||||
notifyChan := cn.CloseNotify()
|
|
||||||
go func() {
|
|
||||||
select {
|
|
||||||
case <-notifyChan:
|
|
||||||
cancel()
|
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
outreq := req.Clone(ctx)
|
|
||||||
if req.ContentLength == 0 {
|
|
||||||
outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
|
|
||||||
}
|
|
||||||
if outreq.Header == nil {
|
|
||||||
outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Director(outreq)
|
|
||||||
outreq.Close = false
|
|
||||||
|
|
||||||
reqUpType := upgradeType(outreq.Header)
|
|
||||||
removeConnectionHeaders(outreq.Header)
|
|
||||||
|
|
||||||
// Remove hop-by-hop headers to the backend. Especially
|
|
||||||
// important is "Connection" because we want a persistent
|
|
||||||
// connection, regardless of what the client sent to us.
|
|
||||||
for _, h := range hopHeaders {
|
|
||||||
hv := outreq.Header.Get(h)
|
|
||||||
if hv == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if h == "Te" && hv == "trailers" {
|
|
||||||
// Issue 21096: tell backend applications that
|
|
||||||
// care about trailer support that we support
|
|
||||||
// trailers. (We do, but we don't go out of
|
|
||||||
// our way to advertise that unless the
|
|
||||||
// incoming client request thought it was
|
|
||||||
// worth mentioning)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
outreq.Header.Del(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
// After stripping all the hop-by-hop connection headers above, add back any
|
|
||||||
// necessary for protocol upgrades, such as for websockets.
|
|
||||||
if reqUpType != "" {
|
|
||||||
outreq.Header.Set("Connection", "Upgrade")
|
|
||||||
outreq.Header.Set("Upgrade", reqUpType)
|
|
||||||
}
|
|
||||||
|
|
||||||
if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
|
|
||||||
// If we aren't the first proxy retain prior
|
|
||||||
// X-Forwarded-For information as a comma+space
|
|
||||||
// separated list and fold multiple headers into one.
|
|
||||||
prior, ok := outreq.Header["X-Forwarded-For"]
|
|
||||||
omit := ok && prior == nil // Issue 38079: nil now means don't populate the header
|
|
||||||
if len(prior) > 0 {
|
|
||||||
clientIP = strings.Join(prior, ", ") + ", " + clientIP
|
|
||||||
}
|
|
||||||
if !omit {
|
|
||||||
outreq.Header.Set("X-Forwarded-For", clientIP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := transport.RoundTrip(outreq)
|
|
||||||
if err != nil {
|
|
||||||
p.getErrorHandler()(rw, outreq, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with 101 Switching Protocols responses: (WebSocket, h2c, etc)
|
|
||||||
if res.StatusCode == http.StatusSwitchingProtocols {
|
|
||||||
if !p.modifyResponse(rw, res, outreq) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.handleUpgradeResponse(rw, outreq, res)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
removeConnectionHeaders(res.Header)
|
|
||||||
|
|
||||||
for _, h := range hopHeaders {
|
|
||||||
res.Header.Del(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !p.modifyResponse(rw, res, outreq) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
copyHeader(rw.Header(), res.Header)
|
|
||||||
|
|
||||||
// The "Trailer" header isn't included in the Transport's response,
|
|
||||||
// at least for *http.Transport. Build it up from Trailer.
|
|
||||||
announcedTrailers := len(res.Trailer)
|
|
||||||
if announcedTrailers > 0 {
|
|
||||||
trailerKeys := make([]string, 0, len(res.Trailer))
|
|
||||||
for k := range res.Trailer {
|
|
||||||
trailerKeys = append(trailerKeys, k)
|
|
||||||
}
|
|
||||||
rw.Header().Add("Trailer", strings.Join(trailerKeys, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
rw.WriteHeader(res.StatusCode)
|
|
||||||
|
|
||||||
err = p.copyResponse(rw, res.Body, p.flushInterval(res))
|
|
||||||
if err != nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
// Since we're streaming the response, if we run into an error all we can do
|
|
||||||
// is abort the request. Issue 23643: ReverseProxy should use ErrAbortHandler
|
|
||||||
// on read error while copying body.
|
|
||||||
if !shouldPanicOnCopyError(req) {
|
|
||||||
p.logf("suppressing panic for copyResponse error in test; copy error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic(http.ErrAbortHandler)
|
|
||||||
}
|
|
||||||
res.Body.Close() // close now, instead of defer, to populate res.Trailer
|
|
||||||
|
|
||||||
if len(res.Trailer) > 0 {
|
|
||||||
// Force chunking if we saw a response trailer.
|
|
||||||
// This prevents net/http from calculating the length for short
|
|
||||||
// bodies and adding a Content-Length.
|
|
||||||
if fl, ok := rw.(http.Flusher); ok {
|
|
||||||
fl.Flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res.Trailer) == announcedTrailers {
|
|
||||||
copyHeader(rw.Header(), res.Trailer)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, vv := range res.Trailer {
|
|
||||||
k = http.TrailerPrefix + k
|
|
||||||
for _, v := range vv {
|
|
||||||
rw.Header().Add(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var inOurTests bool // whether we're in our own tests
|
|
||||||
|
|
||||||
// shouldPanicOnCopyError reports whether the reverse proxy should
|
|
||||||
// panic with http.ErrAbortHandler. This is the right thing to do by
|
|
||||||
// default, but Go 1.10 and earlier did not, so existing unit tests
|
|
||||||
// weren't expecting panics. Only panic in our own tests, or when
|
|
||||||
// running under the HTTP server.
|
|
||||||
func shouldPanicOnCopyError(req *http.Request) bool {
|
|
||||||
if inOurTests {
|
|
||||||
// Our tests know to handle this panic.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if req.Context().Value(http.ServerContextKey) != nil {
|
|
||||||
// We seem to be running under an HTTP server, so
|
|
||||||
// it'll recover the panic.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Otherwise act like Go 1.10 and earlier to not break
|
|
||||||
// existing tests.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
|
|
||||||
// See RFC 7230, section 6.1
|
|
||||||
func removeConnectionHeaders(h http.Header) {
|
|
||||||
for _, f := range h["Connection"] {
|
|
||||||
for _, sf := range strings.Split(f, ",") {
|
|
||||||
if sf = textproto.TrimString(sf); sf != "" {
|
|
||||||
h.Del(sf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// flushInterval returns the p.FlushInterval value, conditionally
|
|
||||||
// overriding its value for a specific request/response.
|
|
||||||
func (p *ReverseProxy) flushInterval(res *http.Response) time.Duration {
|
|
||||||
resCT := res.Header.Get("Content-Type")
|
|
||||||
|
|
||||||
// For Server-Sent Events responses, flush immediately.
|
|
||||||
// The MIME type is defined in https://www.w3.org/TR/eventsource/#text-event-stream
|
|
||||||
if resCT == "text/event-stream" {
|
|
||||||
return -1 // negative means immediately
|
|
||||||
}
|
|
||||||
|
|
||||||
// We might have the case of streaming for which Content-Length might be unset.
|
|
||||||
if res.ContentLength == -1 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.FlushInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader, flushInterval time.Duration) error {
|
|
||||||
if flushInterval != 0 {
|
|
||||||
if wf, ok := dst.(writeFlusher); ok {
|
|
||||||
mlw := &maxLatencyWriter{
|
|
||||||
dst: wf,
|
|
||||||
latency: flushInterval,
|
|
||||||
}
|
|
||||||
defer mlw.stop()
|
|
||||||
|
|
||||||
// set up initial timer so headers get flushed even if body writes are delayed
|
|
||||||
mlw.flushPending = true
|
|
||||||
mlw.t = time.AfterFunc(flushInterval, mlw.delayedFlush)
|
|
||||||
|
|
||||||
dst = mlw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf []byte
|
|
||||||
if p.BufferPool != nil {
|
|
||||||
buf = p.BufferPool.Get()
|
|
||||||
defer p.BufferPool.Put(buf)
|
|
||||||
}
|
|
||||||
_, err := p.copyBuffer(dst, src, buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// copyBuffer returns any write errors or non-EOF read errors, and the amount
|
|
||||||
// of bytes written.
|
|
||||||
func (p *ReverseProxy) copyBuffer(dst io.Writer, src io.Reader, buf []byte) (int64, error) {
|
|
||||||
if len(buf) == 0 {
|
|
||||||
buf = make([]byte, 32*1024)
|
|
||||||
}
|
|
||||||
var written int64
|
|
||||||
for {
|
|
||||||
nr, rerr := src.Read(buf)
|
|
||||||
if rerr != nil && rerr != io.EOF && rerr != context.Canceled {
|
|
||||||
p.logf("httputil: ReverseProxy read error during body copy: %v", rerr)
|
|
||||||
}
|
|
||||||
if nr > 0 {
|
|
||||||
nw, werr := dst.Write(buf[:nr])
|
|
||||||
if nw > 0 {
|
|
||||||
written += int64(nw)
|
|
||||||
}
|
|
||||||
if werr != nil {
|
|
||||||
return written, werr
|
|
||||||
}
|
|
||||||
if nr != nw {
|
|
||||||
return written, io.ErrShortWrite
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rerr != nil {
|
|
||||||
if rerr == io.EOF {
|
|
||||||
rerr = nil
|
|
||||||
}
|
|
||||||
return written, rerr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ReverseProxy) logf(format string, args ...interface{}) {
|
|
||||||
if p.ErrorLog != nil {
|
|
||||||
p.ErrorLog.Printf(format, args...)
|
|
||||||
} else {
|
|
||||||
log.Printf(format, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type writeFlusher interface {
|
|
||||||
io.Writer
|
|
||||||
http.Flusher
|
|
||||||
}
|
|
||||||
|
|
||||||
type maxLatencyWriter struct {
|
|
||||||
dst writeFlusher
|
|
||||||
latency time.Duration // non-zero; negative means to flush immediately
|
|
||||||
|
|
||||||
mu sync.Mutex // protects t, flushPending, and dst.Flush
|
|
||||||
t *time.Timer
|
|
||||||
flushPending bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *maxLatencyWriter) Write(p []byte) (n int, err error) {
|
|
||||||
m.mu.Lock()
|
|
||||||
defer m.mu.Unlock()
|
|
||||||
n, err = m.dst.Write(p)
|
|
||||||
if m.latency < 0 {
|
|
||||||
m.dst.Flush()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if m.flushPending {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if m.t == nil {
|
|
||||||
m.t = time.AfterFunc(m.latency, m.delayedFlush)
|
|
||||||
} else {
|
|
||||||
m.t.Reset(m.latency)
|
|
||||||
}
|
|
||||||
m.flushPending = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *maxLatencyWriter) delayedFlush() {
|
|
||||||
m.mu.Lock()
|
|
||||||
defer m.mu.Unlock()
|
|
||||||
if !m.flushPending { // if stop was called but AfterFunc already started this goroutine
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.dst.Flush()
|
|
||||||
m.flushPending = false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *maxLatencyWriter) stop() {
|
|
||||||
m.mu.Lock()
|
|
||||||
defer m.mu.Unlock()
|
|
||||||
m.flushPending = false
|
|
||||||
if m.t != nil {
|
|
||||||
m.t.Stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func upgradeType(h http.Header) string {
|
|
||||||
if !httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return strings.ToLower(h.Get("Upgrade"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, res *http.Response) {
|
|
||||||
reqUpType := upgradeType(req.Header)
|
|
||||||
resUpType := upgradeType(res.Header)
|
|
||||||
if reqUpType != resUpType {
|
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hj, ok := rw.(http.Hijacker)
|
|
||||||
if !ok {
|
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
backConn, ok := res.Body.(io.ReadWriteCloser)
|
|
||||||
if !ok {
|
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("internal error: 101 switching protocols response with non-writable body"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
backConnCloseCh := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
// Ensure that the cancelation of a request closes the backend.
|
|
||||||
// See issue https://golang.org/issue/35559.
|
|
||||||
select {
|
|
||||||
case <-req.Context().Done():
|
|
||||||
case <-backConnCloseCh:
|
|
||||||
}
|
|
||||||
backConn.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
defer close(backConnCloseCh)
|
|
||||||
|
|
||||||
conn, brw, err := hj.Hijack()
|
|
||||||
if err != nil {
|
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("Hijack failed on protocol switch: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
copyHeader(rw.Header(), res.Header)
|
|
||||||
|
|
||||||
res.Header = rw.Header()
|
|
||||||
res.Body = nil // so res.Write only writes the headers; we have res.Body in backConn above
|
|
||||||
if err := res.Write(brw); err != nil {
|
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("response write: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := brw.Flush(); err != nil {
|
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("response flush: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
errc := make(chan error, 1)
|
|
||||||
spc := switchProtocolCopier{user: conn, backend: backConn}
|
|
||||||
go spc.copyToBackend(errc)
|
|
||||||
go spc.copyFromBackend(errc)
|
|
||||||
<-errc
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// switchProtocolCopier exists so goroutines proxying data back and
|
|
||||||
// forth have nice names in stacks.
|
|
||||||
type switchProtocolCopier struct {
|
|
||||||
user, backend io.ReadWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c switchProtocolCopier) copyFromBackend(errc chan<- error) {
|
|
||||||
_, err := io.Copy(c.user, c.backend)
|
|
||||||
errc <- err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
|
|
||||||
_, err := io.Copy(c.backend, c.user)
|
|
||||||
errc <- err
|
|
||||||
}
|
|
@ -7,9 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrRouterConfigConflict = errors.New("router config conflict")
|
||||||
ErrRouterConfigConflict = errors.New("router config conflict")
|
|
||||||
)
|
|
||||||
|
|
||||||
type routerByHTTPUser map[string][]*Router
|
type routerByHTTPUser map[string][]*Router
|
||||||
|
|
||||||
@ -133,9 +131,11 @@ type ByLocation []*Router
|
|||||||
func (a ByLocation) Len() int {
|
func (a ByLocation) Len() int {
|
||||||
return len(a)
|
return len(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a ByLocation) Swap(i, j int) {
|
func (a ByLocation) Swap(i, j int) {
|
||||||
a[i], a[j] = a[j], a[i]
|
a[i], a[j] = a[j], a[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a ByLocation) Less(i, j int) bool {
|
func (a ByLocation) Less(i, j int) bool {
|
||||||
return strings.Compare(a[i].location, a[j].location) < 0
|
return strings.Compare(a[i].location, a[j].location) < 0
|
||||||
}
|
}
|
||||||
|
@ -19,27 +19,34 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/errors"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/util/log"
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RouteInfo string
|
type RouteInfo string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RouteInfoURL RouteInfo = "url"
|
RouteInfoKey RouteInfo = "routeInfo"
|
||||||
RouteInfoHost RouteInfo = "host"
|
|
||||||
RouteInfoHTTPUser RouteInfo = "httpUser"
|
|
||||||
RouteInfoRemote RouteInfo = "remote"
|
|
||||||
RouteInfoURLHost RouteInfo = "urlHost"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type muxFunc func(net.Conn) (net.Conn, map[string]string, error)
|
type RequestRouteInfo struct {
|
||||||
type httpAuthFunc func(net.Conn, string, string, string) (bool, error)
|
URL string
|
||||||
type hostRewriteFunc func(net.Conn, string) (net.Conn, error)
|
Host string
|
||||||
type successFunc func(net.Conn, map[string]string) error
|
HTTPUser string
|
||||||
|
RemoteAddr string
|
||||||
|
URLHost string
|
||||||
|
Endpoint string
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
muxFunc func(net.Conn) (net.Conn, map[string]string, error)
|
||||||
|
httpAuthFunc func(net.Conn, string, string, string) (bool, error)
|
||||||
|
hostRewriteFunc func(net.Conn, string) (net.Conn, error)
|
||||||
|
successFunc func(net.Conn, map[string]string) error
|
||||||
|
)
|
||||||
|
|
||||||
// Muxer is only used for https and tcpmux proxy.
|
// Muxer is only used for https and tcpmux proxy.
|
||||||
type Muxer struct {
|
type Muxer struct {
|
||||||
@ -60,7 +67,6 @@ func NewMuxer(
|
|||||||
rewriteFunc hostRewriteFunc,
|
rewriteFunc hostRewriteFunc,
|
||||||
timeout time.Duration,
|
timeout time.Duration,
|
||||||
) (mux *Muxer, err error) {
|
) (mux *Muxer, err error) {
|
||||||
|
|
||||||
mux = &Muxer{
|
mux = &Muxer{
|
||||||
listener: listener,
|
listener: listener,
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
@ -74,8 +80,12 @@ func NewMuxer(
|
|||||||
return mux, nil
|
return mux, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChooseEndpointFunc func() (string, error)
|
||||||
|
|
||||||
type CreateConnFunc func(remoteAddr string) (net.Conn, error)
|
type CreateConnFunc func(remoteAddr string) (net.Conn, error)
|
||||||
|
|
||||||
|
type CreateConnByEndpointFunc func(endpoint, remoteAddr string) (net.Conn, error)
|
||||||
|
|
||||||
// RouteConfig is the params used to match HTTP requests
|
// RouteConfig is the params used to match HTTP requests
|
||||||
type RouteConfig struct {
|
type RouteConfig struct {
|
||||||
Domain string
|
Domain string
|
||||||
@ -86,7 +96,9 @@ type RouteConfig struct {
|
|||||||
Headers map[string]string
|
Headers map[string]string
|
||||||
RouteByHTTPUser string
|
RouteByHTTPUser string
|
||||||
|
|
||||||
CreateConnFn CreateConnFunc
|
CreateConnFn CreateConnFunc
|
||||||
|
ChooseEndpointFn ChooseEndpointFunc
|
||||||
|
CreateConnByEndpointFn CreateConnByEndpointFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// listen for a new domain name, if rewriteHost is not empty and rewriteFunc is not nil
|
// listen for a new domain name, if rewriteHost is not empty and rewriteFunc is not nil
|
||||||
@ -111,9 +123,8 @@ func (v *Muxer) Listen(ctx context.Context, cfg *RouteConfig) (l *Listener, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *Muxer) getListener(name, path, httpUser string) (*Listener, bool) {
|
func (v *Muxer) getListener(name, path, httpUser string) (*Listener, bool) {
|
||||||
|
|
||||||
findRouter := func(inName, inPath, inHTTPUser string) (*Listener, bool) {
|
findRouter := func(inName, inPath, inHTTPUser string) (*Listener, bool) {
|
||||||
vr, ok := v.registryRouter.Get(inName, inPath, httpUser)
|
vr, ok := v.registryRouter.Get(inName, inPath, inHTTPUser)
|
||||||
if ok {
|
if ok {
|
||||||
return vr.payload.(*Listener), true
|
return vr.payload.(*Listener), true
|
||||||
}
|
}
|
||||||
@ -167,14 +178,14 @@ func (v *Muxer) run() {
|
|||||||
|
|
||||||
func (v *Muxer) handle(c net.Conn) {
|
func (v *Muxer) handle(c net.Conn) {
|
||||||
if err := c.SetDeadline(time.Now().Add(v.timeout)); err != nil {
|
if err := c.SetDeadline(time.Now().Add(v.timeout)); err != nil {
|
||||||
c.Close()
|
_ = c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sConn, reqInfoMap, err := v.vhostFunc(c)
|
sConn, reqInfoMap, err := v.vhostFunc(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("get hostname from http/https request error: %v", err)
|
log.Debug("get hostname from http/https request error: %v", err)
|
||||||
c.Close()
|
_ = c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,9 +195,12 @@ func (v *Muxer) handle(c net.Conn) {
|
|||||||
l, ok := v.getListener(name, path, httpUser)
|
l, ok := v.getListener(name, path, httpUser)
|
||||||
if !ok {
|
if !ok {
|
||||||
res := notFoundResponse()
|
res := notFoundResponse()
|
||||||
res.Write(c)
|
if res.Body != nil {
|
||||||
|
defer res.Body.Close()
|
||||||
|
}
|
||||||
|
_ = res.Write(c)
|
||||||
log.Debug("http request for host [%s] path [%s] httpUser [%s] not found", name, path, httpUser)
|
log.Debug("http request for host [%s] path [%s] httpUser [%s] not found", name, path, httpUser)
|
||||||
c.Close()
|
_ = c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +208,7 @@ func (v *Muxer) handle(c net.Conn) {
|
|||||||
if v.successFunc != nil {
|
if v.successFunc != nil {
|
||||||
if err := v.successFunc(c, reqInfoMap); err != nil {
|
if err := v.successFunc(c, reqInfoMap); err != nil {
|
||||||
xl.Info("success func failure on vhost connection: %v", err)
|
xl.Info("success func failure on vhost connection: %v", err)
|
||||||
c.Close()
|
_ = c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,17 +217,20 @@ func (v *Muxer) handle(c net.Conn) {
|
|||||||
// then verify user access
|
// then verify user access
|
||||||
if l.mux.authFunc != nil && l.userName != "" && l.passWord != "" {
|
if l.mux.authFunc != nil && l.userName != "" && l.passWord != "" {
|
||||||
bAccess, err := l.mux.authFunc(c, l.userName, l.passWord, reqInfoMap["Authorization"])
|
bAccess, err := l.mux.authFunc(c, l.userName, l.passWord, reqInfoMap["Authorization"])
|
||||||
if bAccess == false || err != nil {
|
if !bAccess || err != nil {
|
||||||
xl.Debug("check http Authorization failed")
|
xl.Debug("check http Authorization failed")
|
||||||
res := noAuthResponse()
|
res := noAuthResponse()
|
||||||
res.Write(c)
|
if res.Body != nil {
|
||||||
c.Close()
|
defer res.Body.Close()
|
||||||
|
}
|
||||||
|
_ = res.Write(c)
|
||||||
|
_ = c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sConn.SetDeadline(time.Time{}); err != nil {
|
if err = sConn.SetDeadline(time.Time{}); err != nil {
|
||||||
c.Close()
|
_ = c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c = sConn
|
c = sConn
|
||||||
|
@ -23,6 +23,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/control/shutdown"
|
||||||
|
"github.com/fatedier/golib/crypto"
|
||||||
|
"github.com/fatedier/golib/errors"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
@ -35,10 +39,6 @@ import (
|
|||||||
"github.com/fatedier/frp/server/controller"
|
"github.com/fatedier/frp/server/controller"
|
||||||
"github.com/fatedier/frp/server/metrics"
|
"github.com/fatedier/frp/server/metrics"
|
||||||
"github.com/fatedier/frp/server/proxy"
|
"github.com/fatedier/frp/server/proxy"
|
||||||
|
|
||||||
"github.com/fatedier/golib/control/shutdown"
|
|
||||||
"github.com/fatedier/golib/crypto"
|
|
||||||
"github.com/fatedier/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ControlManager struct {
|
type ControlManager struct {
|
||||||
@ -154,7 +154,6 @@ func NewControl(
|
|||||||
loginMsg *msg.Login,
|
loginMsg *msg.Login,
|
||||||
serverCfg config.ServerCommonConf,
|
serverCfg config.ServerCommonConf,
|
||||||
) *Control {
|
) *Control {
|
||||||
|
|
||||||
poolCount := loginMsg.PoolCount
|
poolCount := loginMsg.PoolCount
|
||||||
if poolCount > int(serverCfg.MaxPoolCount) {
|
if poolCount > int(serverCfg.MaxPoolCount) {
|
||||||
poolCount = int(serverCfg.MaxPoolCount)
|
poolCount = int(serverCfg.MaxPoolCount)
|
||||||
@ -193,7 +192,7 @@ func (ctl *Control) Start() {
|
|||||||
ServerUDPPort: ctl.serverCfg.BindUDPPort,
|
ServerUDPPort: ctl.serverCfg.BindUDPPort,
|
||||||
Error: "",
|
Error: "",
|
||||||
}
|
}
|
||||||
msg.WriteMsg(ctl.conn, loginRespMsg)
|
_ = msg.WriteMsg(ctl.conn, loginRespMsg)
|
||||||
|
|
||||||
go ctl.writer()
|
go ctl.writer()
|
||||||
for i := 0; i < ctl.poolCount; i++ {
|
for i := 0; i < ctl.poolCount; i++ {
|
||||||
@ -270,7 +269,7 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// When we get a work connection from pool, replace it with a new one.
|
// When we get a work connection from pool, replace it with a new one.
|
||||||
errors.PanicToError(func() {
|
_ = errors.PanicToError(func() {
|
||||||
ctl.sendCh <- &msg.ReqWorkConn{}
|
ctl.sendCh <- &msg.ReqWorkConn{}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -388,7 +387,7 @@ func (ctl *Control) stoper() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
ctl.pluginManager.CloseProxy(notifyContent)
|
_ = ctl.pluginManager.CloseProxy(notifyContent)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,7 +466,7 @@ func (ctl *Control) manager() {
|
|||||||
}
|
}
|
||||||
ctl.sendCh <- resp
|
ctl.sendCh <- resp
|
||||||
case *msg.CloseProxy:
|
case *msg.CloseProxy:
|
||||||
ctl.CloseProxy(m)
|
_ = ctl.CloseProxy(m)
|
||||||
xl.Info("close proxy [%s] success", m.ProxyName)
|
xl.Info("close proxy [%s] success", m.ProxyName)
|
||||||
case *msg.Ping:
|
case *msg.Ping:
|
||||||
content := &plugin.PingContent{
|
content := &plugin.PingContent{
|
||||||
@ -528,13 +527,13 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
|
|||||||
err = fmt.Errorf("exceed the max_ports_per_client")
|
err = fmt.Errorf("exceed the max_ports_per_client")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctl.portsUsedNum = ctl.portsUsedNum + pxy.GetUsedPortsNum()
|
ctl.portsUsedNum += pxy.GetUsedPortsNum()
|
||||||
ctl.mu.Unlock()
|
ctl.mu.Unlock()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctl.mu.Lock()
|
ctl.mu.Lock()
|
||||||
ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum()
|
ctl.portsUsedNum -= pxy.GetUsedPortsNum()
|
||||||
ctl.mu.Unlock()
|
ctl.mu.Unlock()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -570,7 +569,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctl.serverCfg.MaxPortsPerClient > 0 {
|
if ctl.serverCfg.MaxPortsPerClient > 0 {
|
||||||
ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum()
|
ctl.portsUsedNum -= pxy.GetUsedPortsNum()
|
||||||
}
|
}
|
||||||
pxy.Close()
|
pxy.Close()
|
||||||
ctl.pxyManager.Del(pxy.GetName())
|
ctl.pxyManager.Del(pxy.GetName())
|
||||||
@ -590,7 +589,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
ctl.pluginManager.CloseProxy(notifyContent)
|
_ = ctl.pluginManager.CloseProxy(notifyContent)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -21,11 +21,11 @@ import (
|
|||||||
"net/http/pprof"
|
"net/http/pprof"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatedier/frp/assets"
|
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/assets"
|
||||||
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -92,6 +92,8 @@ func (svr *Service) RunDashboardServer(address string) (err error) {
|
|||||||
}
|
}
|
||||||
ln = tls.NewListener(ln, tlsCfg)
|
ln = tls.NewListener(ln, tlsCfg)
|
||||||
}
|
}
|
||||||
go server.Serve(ln)
|
go func() {
|
||||||
|
_ = server.Serve(ln)
|
||||||
|
}()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
"github.com/fatedier/frp/pkg/metrics/mem"
|
"github.com/fatedier/frp/pkg/metrics/mem"
|
||||||
"github.com/fatedier/frp/pkg/util/log"
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
"github.com/fatedier/frp/pkg/util/version"
|
"github.com/fatedier/frp/pkg/util/version"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type GeneralResponse struct {
|
type GeneralResponse struct {
|
||||||
@ -63,7 +63,7 @@ func (svr *Service) APIServerInfo(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||||
w.WriteHeader(res.Code)
|
w.WriteHeader(res.Code)
|
||||||
if len(res.Msg) > 0 {
|
if len(res.Msg) > 0 {
|
||||||
w.Write([]byte(res.Msg))
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ func (svr *Service) APIProxyByType(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||||
w.WriteHeader(res.Code)
|
w.WriteHeader(res.Code)
|
||||||
if len(res.Msg) > 0 {
|
if len(res.Msg) > 0 {
|
||||||
w.Write([]byte(res.Msg))
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
log.Info("Http request: [%s]", r.URL.Path)
|
log.Info("Http request: [%s]", r.URL.Path)
|
||||||
@ -245,12 +245,12 @@ func (svr *Service) APIProxyByTypeAndName(w http.ResponseWriter, r *http.Request
|
|||||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||||
w.WriteHeader(res.Code)
|
w.WriteHeader(res.Code)
|
||||||
if len(res.Msg) > 0 {
|
if len(res.Msg) > 0 {
|
||||||
w.Write([]byte(res.Msg))
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
log.Info("Http request: [%s]", r.URL.Path)
|
log.Info("Http request: [%s]", r.URL.Path)
|
||||||
|
|
||||||
proxyStatsResp := GetProxyStatsResp{}
|
var proxyStatsResp GetProxyStatsResp
|
||||||
proxyStatsResp, res.Code, res.Msg = svr.getProxyStatsByTypeAndName(proxyType, name)
|
proxyStatsResp, res.Code, res.Msg = svr.getProxyStatsByTypeAndName(proxyType, name)
|
||||||
if res.Code != 200 {
|
if res.Code != 200 {
|
||||||
return
|
return
|
||||||
@ -313,7 +313,7 @@ func (svr *Service) APIProxyTraffic(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||||
w.WriteHeader(res.Code)
|
w.WriteHeader(res.Code)
|
||||||
if len(res.Msg) > 0 {
|
if len(res.Msg) > 0 {
|
||||||
w.Write([]byte(res.Msg))
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
log.Info("Http request: [%s]", r.URL.Path)
|
log.Info("Http request: [%s]", r.URL.Path)
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type HTTPGroupController struct {
|
type HTTPGroupController struct {
|
||||||
// groups by indexKey
|
// groups indexed by group name
|
||||||
groups map[string]*HTTPGroup
|
groups map[string]*HTTPGroup
|
||||||
|
|
||||||
// register createConn for each group to vhostRouter.
|
// register createConn for each group to vhostRouter.
|
||||||
@ -31,7 +31,6 @@ func (ctl *HTTPGroupController) Register(
|
|||||||
proxyName, group, groupKey string,
|
proxyName, group, groupKey string,
|
||||||
routeConfig vhost.RouteConfig,
|
routeConfig vhost.RouteConfig,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
|
|
||||||
indexKey := group
|
indexKey := group
|
||||||
ctl.mu.Lock()
|
ctl.mu.Lock()
|
||||||
g, ok := ctl.groups[indexKey]
|
g, ok := ctl.groups[indexKey]
|
||||||
@ -66,7 +65,7 @@ type HTTPGroup struct {
|
|||||||
location string
|
location string
|
||||||
routeByHTTPUser string
|
routeByHTTPUser string
|
||||||
|
|
||||||
// CreateConnFuncs indexed by echo proxy name
|
// CreateConnFuncs indexed by proxy name
|
||||||
createFuncs map[string]vhost.CreateConnFunc
|
createFuncs map[string]vhost.CreateConnFunc
|
||||||
pxyNames []string
|
pxyNames []string
|
||||||
index uint64
|
index uint64
|
||||||
@ -86,13 +85,14 @@ func (g *HTTPGroup) Register(
|
|||||||
proxyName, group, groupKey string,
|
proxyName, group, groupKey string,
|
||||||
routeConfig vhost.RouteConfig,
|
routeConfig vhost.RouteConfig,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
|
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
defer g.mu.Unlock()
|
defer g.mu.Unlock()
|
||||||
if len(g.createFuncs) == 0 {
|
if len(g.createFuncs) == 0 {
|
||||||
// the first proxy in this group
|
// the first proxy in this group
|
||||||
tmp := routeConfig // copy object
|
tmp := routeConfig // copy object
|
||||||
tmp.CreateConnFn = g.createConn
|
tmp.CreateConnFn = g.createConn
|
||||||
|
tmp.ChooseEndpointFn = g.chooseEndpoint
|
||||||
|
tmp.CreateConnByEndpointFn = g.createConnByEndpoint
|
||||||
err = g.ctl.vhostRouter.Add(routeConfig.Domain, routeConfig.Location, routeConfig.RouteByHTTPUser, &tmp)
|
err = g.ctl.vhostRouter.Add(routeConfig.Domain, routeConfig.Location, routeConfig.RouteByHTTPUser, &tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -152,7 +152,7 @@ func (g *HTTPGroup) createConn(remoteAddr string) (net.Conn, error) {
|
|||||||
routeByHTTPUser := g.routeByHTTPUser
|
routeByHTTPUser := g.routeByHTTPUser
|
||||||
if len(g.pxyNames) > 0 {
|
if len(g.pxyNames) > 0 {
|
||||||
name := g.pxyNames[int(newIndex)%len(g.pxyNames)]
|
name := g.pxyNames[int(newIndex)%len(g.pxyNames)]
|
||||||
f, _ = g.createFuncs[name]
|
f = g.createFuncs[name]
|
||||||
}
|
}
|
||||||
g.mu.RUnlock()
|
g.mu.RUnlock()
|
||||||
|
|
||||||
@ -163,3 +163,36 @@ func (g *HTTPGroup) createConn(remoteAddr string) (net.Conn, error) {
|
|||||||
|
|
||||||
return f(remoteAddr)
|
return f(remoteAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *HTTPGroup) chooseEndpoint() (string, error) {
|
||||||
|
newIndex := atomic.AddUint64(&g.index, 1)
|
||||||
|
name := ""
|
||||||
|
|
||||||
|
g.mu.RLock()
|
||||||
|
group := g.group
|
||||||
|
domain := g.domain
|
||||||
|
location := g.location
|
||||||
|
routeByHTTPUser := g.routeByHTTPUser
|
||||||
|
if len(g.pxyNames) > 0 {
|
||||||
|
name = g.pxyNames[int(newIndex)%len(g.pxyNames)]
|
||||||
|
}
|
||||||
|
g.mu.RUnlock()
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
return "", fmt.Errorf("no healthy endpoint for http group [%s], domain [%s], location [%s], routeByHTTPUser [%s]",
|
||||||
|
group, domain, location, routeByHTTPUser)
|
||||||
|
}
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *HTTPGroup) createConnByEndpoint(endpoint, remoteAddr string) (net.Conn, error) {
|
||||||
|
var f vhost.CreateConnFunc
|
||||||
|
g.mu.RLock()
|
||||||
|
f = g.createFuncs[endpoint]
|
||||||
|
g.mu.RUnlock()
|
||||||
|
|
||||||
|
if f == nil {
|
||||||
|
return nil, fmt.Errorf("no CreateConnFunc for endpoint [%s] in group [%s]", endpoint, g.group)
|
||||||
|
}
|
||||||
|
return f(remoteAddr)
|
||||||
|
}
|
||||||
|
@ -19,9 +19,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/fatedier/frp/server/ports"
|
|
||||||
|
|
||||||
gerr "github.com/fatedier/golib/errors"
|
gerr "github.com/fatedier/golib/errors"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/server/ports"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TCPGroupCtl manage all TCPGroups
|
// TCPGroupCtl manage all TCPGroups
|
||||||
@ -44,8 +44,8 @@ func NewTCPGroupCtl(portManager *ports.Manager) *TCPGroupCtl {
|
|||||||
// Listen is the wrapper for TCPGroup's Listen
|
// Listen is the wrapper for TCPGroup's Listen
|
||||||
// If there are no group, we will create one here
|
// If there are no group, we will create one here
|
||||||
func (tgc *TCPGroupCtl) Listen(proxyName string, group string, groupKey string,
|
func (tgc *TCPGroupCtl) Listen(proxyName string, group string, groupKey string,
|
||||||
addr string, port int) (l net.Listener, realPort int, err error) {
|
addr string, port int,
|
||||||
|
) (l net.Listener, realPort int, err error) {
|
||||||
tgc.mu.Lock()
|
tgc.mu.Lock()
|
||||||
tcpGroup, ok := tgc.groups[group]
|
tcpGroup, ok := tgc.groups[group]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -73,7 +73,6 @@ type TCPGroup struct {
|
|||||||
realPort int
|
realPort int
|
||||||
|
|
||||||
acceptCh chan net.Conn
|
acceptCh chan net.Conn
|
||||||
index uint64
|
|
||||||
tcpLn net.Listener
|
tcpLn net.Listener
|
||||||
lns []*TCPGroupListener
|
lns []*TCPGroupListener
|
||||||
ctl *TCPGroupCtl
|
ctl *TCPGroupCtl
|
||||||
|
@ -20,11 +20,11 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
gerr "github.com/fatedier/golib/errors"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/consts"
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
"github.com/fatedier/frp/pkg/util/tcpmux"
|
"github.com/fatedier/frp/pkg/util/tcpmux"
|
||||||
"github.com/fatedier/frp/pkg/util/vhost"
|
"github.com/fatedier/frp/pkg/util/vhost"
|
||||||
|
|
||||||
gerr "github.com/fatedier/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TCPMuxGroupCtl manage all TCPMuxGroups
|
// TCPMuxGroupCtl manage all TCPMuxGroups
|
||||||
@ -51,7 +51,6 @@ func (tmgc *TCPMuxGroupCtl) Listen(
|
|||||||
multiplexer, group, groupKey string,
|
multiplexer, group, groupKey string,
|
||||||
routeConfig vhost.RouteConfig,
|
routeConfig vhost.RouteConfig,
|
||||||
) (l net.Listener, err error) {
|
) (l net.Listener, err error) {
|
||||||
|
|
||||||
tmgc.mu.Lock()
|
tmgc.mu.Lock()
|
||||||
tcpMuxGroup, ok := tmgc.groups[group]
|
tcpMuxGroup, ok := tmgc.groups[group]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -84,7 +83,6 @@ type TCPMuxGroup struct {
|
|||||||
routeByHTTPUser string
|
routeByHTTPUser string
|
||||||
|
|
||||||
acceptCh chan net.Conn
|
acceptCh chan net.Conn
|
||||||
index uint64
|
|
||||||
tcpMuxLn net.Listener
|
tcpMuxLn net.Listener
|
||||||
lns []*TCPMuxGroupListener
|
lns []*TCPMuxGroupListener
|
||||||
ctl *TCPMuxGroupCtl
|
ctl *TCPMuxGroupCtl
|
||||||
@ -108,7 +106,6 @@ func (tmg *TCPMuxGroup) HTTPConnectListen(
|
|||||||
group, groupKey string,
|
group, groupKey string,
|
||||||
routeConfig vhost.RouteConfig,
|
routeConfig vhost.RouteConfig,
|
||||||
) (ln *TCPMuxGroupListener, err error) {
|
) (ln *TCPMuxGroupListener, err error) {
|
||||||
|
|
||||||
tmg.mu.Lock()
|
tmg.mu.Lock()
|
||||||
defer tmg.mu.Unlock()
|
defer tmg.mu.Unlock()
|
||||||
if len(tmg.lns) == 0 {
|
if len(tmg.lns) == 0 {
|
||||||
|
@ -19,13 +19,13 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
frpIo "github.com/fatedier/golib/io"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
"github.com/fatedier/frp/pkg/util/vhost"
|
"github.com/fatedier/frp/pkg/util/vhost"
|
||||||
"github.com/fatedier/frp/server/metrics"
|
"github.com/fatedier/frp/server/metrics"
|
||||||
|
|
||||||
frpIo "github.com/fatedier/golib/io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type HTTPProxy struct {
|
type HTTPProxy struct {
|
||||||
@ -89,7 +89,7 @@ func (pxy *HTTPProxy) Run() (remoteAddr string, err error) {
|
|||||||
pxy.rc.HTTPReverseProxy.UnRegister(tmpRouteConfig)
|
pxy.rc.HTTPReverseProxy.UnRegister(tmpRouteConfig)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(pxy.serverCfg.VhostHTTPPort)))
|
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, pxy.serverCfg.VhostHTTPPort))
|
||||||
xl.Info("http proxy listen for host [%s] location [%s] group [%s], routeByHTTPUser [%s]",
|
xl.Info("http proxy listen for host [%s] location [%s] group [%s], routeByHTTPUser [%s]",
|
||||||
routeConfig.Domain, routeConfig.Location, pxy.cfg.Group, pxy.cfg.RouteByHTTPUser)
|
routeConfig.Domain, routeConfig.Location, pxy.cfg.Group, pxy.cfg.RouteByHTTPUser)
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func (pxy *HTTPSProxy) Run() (remoteAddr string, err error) {
|
|||||||
}
|
}
|
||||||
xl.Info("https proxy listen for host [%s]", routeConfig.Domain)
|
xl.Info("https proxy listen for host [%s]", routeConfig.Domain)
|
||||||
pxy.listeners = append(pxy.listeners, l)
|
pxy.listeners = append(pxy.listeners, l)
|
||||||
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(pxy.serverCfg.VhostHTTPSPort)))
|
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, pxy.serverCfg.VhostHTTPSPort))
|
||||||
}
|
}
|
||||||
|
|
||||||
pxy.startListenHandler(pxy, HandleUserTCPConnection)
|
pxy.startListenHandler(pxy, HandleUserTCPConnection)
|
||||||
|
@ -23,6 +23,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
frpIo "github.com/fatedier/golib/io"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||||
@ -30,8 +32,6 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
"github.com/fatedier/frp/server/controller"
|
"github.com/fatedier/frp/server/controller"
|
||||||
"github.com/fatedier/frp/server/metrics"
|
"github.com/fatedier/frp/server/metrics"
|
||||||
|
|
||||||
frpIo "github.com/fatedier/golib/io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type GetWorkConnFn func() (net.Conn, error)
|
type GetWorkConnFn func() (net.Conn, error)
|
||||||
@ -184,8 +184,8 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, net.Conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.ResourceController, poolCount int,
|
func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.ResourceController, poolCount int,
|
||||||
getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf, serverCfg config.ServerCommonConf) (pxy Proxy, err error) {
|
getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf, serverCfg config.ServerCommonConf,
|
||||||
|
) (pxy Proxy, err error) {
|
||||||
xl := xlog.FromContextSafe(ctx).Spawn().AppendPrefix(pxyConf.GetBaseInfo().ProxyName)
|
xl := xlog.FromContextSafe(ctx).Spawn().AppendPrefix(pxyConf.GetBaseInfo().ProxyName)
|
||||||
basePxy := BaseProxy{
|
basePxy := BaseProxy{
|
||||||
name: pxyConf.GetBaseInfo().ProxyName,
|
name: pxyConf.GetBaseInfo().ProxyName,
|
||||||
|
@ -22,14 +22,14 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/errors"
|
||||||
|
frpIo "github.com/fatedier/golib/io"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
"github.com/fatedier/frp/pkg/proto/udp"
|
"github.com/fatedier/frp/pkg/proto/udp"
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
"github.com/fatedier/frp/server/metrics"
|
"github.com/fatedier/frp/server/metrics"
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
|
||||||
frpIo "github.com/fatedier/golib/io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type UDPProxy struct {
|
type UDPProxy struct {
|
||||||
@ -98,18 +98,20 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
|
|||||||
)
|
)
|
||||||
xl.Trace("loop waiting message from udp workConn")
|
xl.Trace("loop waiting message from udp workConn")
|
||||||
// client will send heartbeat in workConn for keeping alive
|
// client will send heartbeat in workConn for keeping alive
|
||||||
conn.SetReadDeadline(time.Now().Add(time.Duration(60) * time.Second))
|
_ = conn.SetReadDeadline(time.Now().Add(time.Duration(60) * time.Second))
|
||||||
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
|
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
|
||||||
xl.Warn("read from workConn for udp error: %v", errRet)
|
xl.Warn("read from workConn for udp error: %v", errRet)
|
||||||
conn.Close()
|
_ = conn.Close()
|
||||||
// notify proxy to start a new work connection
|
// notify proxy to start a new work connection
|
||||||
// ignore error here, it means the proxy is closed
|
// ignore error here, it means the proxy is closed
|
||||||
errors.PanicToError(func() {
|
_ = errors.PanicToError(func() {
|
||||||
pxy.checkCloseCh <- 1
|
pxy.checkCloseCh <- 1
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn.SetReadDeadline(time.Time{})
|
if err := conn.SetReadDeadline(time.Time{}); err != nil {
|
||||||
|
xl.Warn("set read deadline error: %v", err)
|
||||||
|
}
|
||||||
switch m := rawMsg.(type) {
|
switch m := rawMsg.(type) {
|
||||||
case *msg.Ping:
|
case *msg.Ping:
|
||||||
xl.Trace("udp work conn get ping message")
|
xl.Trace("udp work conn get ping message")
|
||||||
|
@ -17,10 +17,10 @@ package proxy
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/errors"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
"github.com/fatedier/frp/pkg/msg"
|
"github.com/fatedier/frp/pkg/msg"
|
||||||
|
|
||||||
"github.com/fatedier/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type XTCPProxy struct {
|
type XTCPProxy struct {
|
||||||
@ -91,7 +91,7 @@ func (pxy *XTCPProxy) GetConf() config.ProxyConf {
|
|||||||
func (pxy *XTCPProxy) Close() {
|
func (pxy *XTCPProxy) Close() {
|
||||||
pxy.BaseProxy.Close()
|
pxy.BaseProxy.Close()
|
||||||
pxy.rc.NatHoleController.CloseClient(pxy.GetName())
|
pxy.rc.NatHoleController.CloseClient(pxy.GetName())
|
||||||
errors.PanicToError(func() {
|
_ = errors.PanicToError(func() {
|
||||||
close(pxy.closeCh)
|
close(pxy.closeCh)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/net/mux"
|
||||||
|
fmux "github.com/hashicorp/yamux"
|
||||||
|
|
||||||
"github.com/fatedier/frp/assets"
|
"github.com/fatedier/frp/assets"
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
"github.com/fatedier/frp/pkg/config"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
@ -47,9 +50,6 @@ import (
|
|||||||
"github.com/fatedier/frp/server/ports"
|
"github.com/fatedier/frp/server/ports"
|
||||||
"github.com/fatedier/frp/server/proxy"
|
"github.com/fatedier/frp/server/proxy"
|
||||||
"github.com/fatedier/frp/server/visitor"
|
"github.com/fatedier/frp/server/visitor"
|
||||||
|
|
||||||
"github.com/fatedier/golib/net/mux"
|
|
||||||
fmux "github.com/hashicorp/yamux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -127,26 +127,26 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
|||||||
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.TCPMuxHTTPConnectPort))
|
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.TCPMuxHTTPConnectPort))
|
||||||
l, err = net.Listen("tcp", address)
|
l, err = net.Listen("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Create server listener error, %v", err)
|
err = fmt.Errorf("create server listener error, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
svr.rc.TCPMuxHTTPConnectMuxer, err = tcpmux.NewHTTPConnectTCPMuxer(l, cfg.TCPMuxPassthrough, vhostReadWriteTimeout)
|
svr.rc.TCPMuxHTTPConnectMuxer, err = tcpmux.NewHTTPConnectTCPMuxer(l, cfg.TCPMuxPassthrough, vhostReadWriteTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Create vhost tcpMuxer error, %v", err)
|
err = fmt.Errorf("create vhost tcpMuxer error, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("tcpmux httpconnect multiplexer listen on %s, passthough: %v", address, cfg.TCPMuxPassthrough)
|
log.Info("tcpmux httpconnect multiplexer listen on %s, passthough: %v", address, cfg.TCPMuxPassthrough)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init all plugins
|
// Init all plugins
|
||||||
plugin_names := make([]string, 0, len(cfg.HTTPPlugins))
|
pluginNames := make([]string, 0, len(cfg.HTTPPlugins))
|
||||||
for n := range cfg.HTTPPlugins {
|
for n := range cfg.HTTPPlugins {
|
||||||
plugin_names = append(plugin_names, n)
|
pluginNames = append(pluginNames, n)
|
||||||
}
|
}
|
||||||
sort.Strings(plugin_names)
|
sort.Strings(pluginNames)
|
||||||
|
|
||||||
for _, name := range plugin_names {
|
for _, name := range pluginNames {
|
||||||
svr.pluginManager.Register(plugin.NewHTTPPluginOptions(cfg.HTTPPlugins[name]))
|
svr.pluginManager.Register(plugin.NewHTTPPluginOptions(cfg.HTTPPlugins[name]))
|
||||||
log.Info("plugin [%s] has been registered", name)
|
log.Info("plugin [%s] has been registered", name)
|
||||||
}
|
}
|
||||||
@ -181,13 +181,15 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
|||||||
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.BindPort))
|
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.BindPort))
|
||||||
ln, err := net.Listen("tcp", address)
|
ln, err := net.Listen("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Create server listener error, %v", err)
|
err = fmt.Errorf("create server listener error, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
svr.muxer = mux.NewMux(ln)
|
svr.muxer = mux.NewMux(ln)
|
||||||
svr.muxer.SetKeepAlive(time.Duration(cfg.TCPKeepAlive) * time.Second)
|
svr.muxer.SetKeepAlive(time.Duration(cfg.TCPKeepAlive) * time.Second)
|
||||||
go svr.muxer.Serve()
|
go func() {
|
||||||
|
_ = svr.muxer.Serve()
|
||||||
|
}()
|
||||||
ln = svr.muxer.DefaultListener()
|
ln = svr.muxer.DefaultListener()
|
||||||
|
|
||||||
svr.listener = ln
|
svr.listener = ln
|
||||||
@ -198,7 +200,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
|||||||
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.KCPBindPort))
|
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.KCPBindPort))
|
||||||
svr.kcpListener, err = frpNet.ListenKcp(address)
|
svr.kcpListener, err = frpNet.ListenKcp(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Listen on kcp address udp %s error: %v", address, err)
|
err = fmt.Errorf("listen on kcp address udp %s error: %v", address, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("frps kcp listen on udp %s", address)
|
log.Info("frps kcp listen on udp %s", address)
|
||||||
@ -229,11 +231,13 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
|||||||
} else {
|
} else {
|
||||||
l, err = net.Listen("tcp", address)
|
l, err = net.Listen("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Create vhost http listener error, %v", err)
|
err = fmt.Errorf("create vhost http listener error, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
go server.Serve(l)
|
go func() {
|
||||||
|
_ = server.Serve(l)
|
||||||
|
}()
|
||||||
log.Info("http service listen on %s", address)
|
log.Info("http service listen on %s", address)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +250,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
|||||||
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.VhostHTTPSPort))
|
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.VhostHTTPSPort))
|
||||||
l, err = net.Listen("tcp", address)
|
l, err = net.Listen("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Create server listener error, %v", err)
|
err = fmt.Errorf("create server listener error, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("https service listen on %s", address)
|
log.Info("https service listen on %s", address)
|
||||||
@ -254,7 +258,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
|||||||
|
|
||||||
svr.rc.VhostHTTPSMuxer, err = vhost.NewHTTPSMuxer(l, vhostReadWriteTimeout)
|
svr.rc.VhostHTTPSMuxer, err = vhost.NewHTTPSMuxer(l, vhostReadWriteTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Create vhost httpsMuxer error, %v", err)
|
err = fmt.Errorf("create vhost httpsMuxer error, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,7 +275,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
|||||||
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.BindUDPPort))
|
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.BindUDPPort))
|
||||||
nc, err = nathole.NewController(address)
|
nc, err = nathole.NewController(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Create nat hole controller error, %v", err)
|
err = fmt.Errorf("create nat hole controller error, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
svr.rc.NatHoleController = nc
|
svr.rc.NatHoleController = nc
|
||||||
@ -287,7 +291,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
|
|||||||
address := net.JoinHostPort(cfg.DashboardAddr, strconv.Itoa(cfg.DashboardPort))
|
address := net.JoinHostPort(cfg.DashboardAddr, strconv.Itoa(cfg.DashboardPort))
|
||||||
err = svr.RunDashboardServer(address)
|
err = svr.RunDashboardServer(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Create dashboard web server error, %v", err)
|
err = fmt.Errorf("create dashboard web server error, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("Dashboard listen on %s", address)
|
log.Info("Dashboard listen on %s", address)
|
||||||
@ -324,13 +328,13 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
conn.SetReadDeadline(time.Now().Add(connReadTimeout))
|
_ = conn.SetReadDeadline(time.Now().Add(connReadTimeout))
|
||||||
if rawMsg, err = msg.ReadMsg(conn); err != nil {
|
if rawMsg, err = msg.ReadMsg(conn); err != nil {
|
||||||
log.Trace("Failed to read message: %v", err)
|
log.Trace("Failed to read message: %v", err)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn.SetReadDeadline(time.Time{})
|
_ = conn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
switch m := rawMsg.(type) {
|
switch m := rawMsg.(type) {
|
||||||
case *msg.Login:
|
case *msg.Login:
|
||||||
@ -349,7 +353,7 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
|
|||||||
// Otherwise send success message in control's work goroutine.
|
// Otherwise send success message in control's work goroutine.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xl.Warn("register control error: %v", err)
|
xl.Warn("register control error: %v", err)
|
||||||
msg.WriteMsg(conn, &msg.LoginResp{
|
_ = msg.WriteMsg(conn, &msg.LoginResp{
|
||||||
Version: version.Full(),
|
Version: version.Full(),
|
||||||
Error: util.GenerateResponseErrorString("register control error", err, svr.cfg.DetailedErrorsToClient),
|
Error: util.GenerateResponseErrorString("register control error", err, svr.cfg.DetailedErrorsToClient),
|
||||||
})
|
})
|
||||||
@ -362,13 +366,13 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
|
|||||||
case *msg.NewVisitorConn:
|
case *msg.NewVisitorConn:
|
||||||
if err = svr.RegisterVisitorConn(conn, m); err != nil {
|
if err = svr.RegisterVisitorConn(conn, m); err != nil {
|
||||||
xl.Warn("register visitor conn error: %v", err)
|
xl.Warn("register visitor conn error: %v", err)
|
||||||
msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
_ = msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
||||||
ProxyName: m.ProxyName,
|
ProxyName: m.ProxyName,
|
||||||
Error: util.GenerateResponseErrorString("register visitor conn error", err, svr.cfg.DetailedErrorsToClient),
|
Error: util.GenerateResponseErrorString("register visitor conn error", err, svr.cfg.DetailedErrorsToClient),
|
||||||
})
|
})
|
||||||
conn.Close()
|
conn.Close()
|
||||||
} else {
|
} else {
|
||||||
msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
_ = msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
||||||
ProxyName: m.ProxyName,
|
ProxyName: m.ProxyName,
|
||||||
Error: "",
|
Error: "",
|
||||||
})
|
})
|
||||||
@ -504,7 +508,7 @@ func (svr *Service) RegisterWorkConn(workConn net.Conn, newMsg *msg.NewWorkConn)
|
|||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xl.Warn("invalid NewWorkConn with run id [%s]", newMsg.RunID)
|
xl.Warn("invalid NewWorkConn with run id [%s]", newMsg.RunID)
|
||||||
msg.WriteMsg(workConn, &msg.StartWorkConn{
|
_ = msg.WriteMsg(workConn, &msg.StartWorkConn{
|
||||||
Error: util.GenerateResponseErrorString("invalid NewWorkConn", err, ctl.serverCfg.DetailedErrorsToClient),
|
Error: util.GenerateResponseErrorString("invalid NewWorkConn", err, ctl.serverCfg.DetailedErrorsToClient),
|
||||||
})
|
})
|
||||||
return fmt.Errorf("invalid NewWorkConn with run id [%s]", newMsg.RunID)
|
return fmt.Errorf("invalid NewWorkConn with run id [%s]", newMsg.RunID)
|
||||||
|
@ -20,10 +20,10 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
frpIo "github.com/fatedier/golib/io"
|
||||||
|
|
||||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
|
|
||||||
frpIo "github.com/fatedier/golib/io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Manager for visitor listeners.
|
// Manager for visitor listeners.
|
||||||
@ -57,8 +57,8 @@ func (vm *Manager) Listen(name string, sk string) (l *frpNet.CustomListener, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey string,
|
func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey string,
|
||||||
useEncryption bool, useCompression bool) (err error) {
|
useEncryption bool, useCompression bool,
|
||||||
|
) (err error) {
|
||||||
vm.mu.RLock()
|
vm.mu.RLock()
|
||||||
defer vm.mu.RUnlock()
|
defer vm.mu.RUnlock()
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/onsi/ginkgo"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/transport"
|
"github.com/fatedier/frp/pkg/transport"
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
@ -12,18 +14,16 @@ import (
|
|||||||
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
|
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("[Feature: Basic]", func() {
|
var _ = ginkgo.Describe("[Feature: Basic]", func() {
|
||||||
f := framework.NewDefaultFramework()
|
f := framework.NewDefaultFramework()
|
||||||
|
|
||||||
Describe("TCP && UDP", func() {
|
ginkgo.Describe("TCP && UDP", func() {
|
||||||
types := []string{"tcp", "udp"}
|
types := []string{"tcp", "udp"}
|
||||||
for _, t := range types {
|
for _, t := range types {
|
||||||
proxyType := t
|
proxyType := t
|
||||||
It(fmt.Sprintf("Expose a %s echo server", strings.ToUpper(proxyType)), func() {
|
ginkgo.It(fmt.Sprintf("Expose a %s echo server", strings.ToUpper(proxyType)), func() {
|
||||||
serverConf := consts.DefaultServerConfig
|
serverConf := consts.DefaultServerConfig
|
||||||
clientConf := consts.DefaultClientConfig
|
clientConf := consts.DefaultClientConfig
|
||||||
|
|
||||||
@ -93,8 +93,8 @@ var _ = Describe("[Feature: Basic]", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("HTTP", func() {
|
ginkgo.Describe("HTTP", func() {
|
||||||
It("proxy to HTTP server", func() {
|
ginkgo.It("proxy to HTTP server", func() {
|
||||||
serverConf := consts.DefaultServerConfig
|
serverConf := consts.DefaultServerConfig
|
||||||
vhostHTTPPort := f.AllocPort()
|
vhostHTTPPort := f.AllocPort()
|
||||||
serverConf += fmt.Sprintf(`
|
serverConf += fmt.Sprintf(`
|
||||||
@ -175,8 +175,8 @@ var _ = Describe("[Feature: Basic]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("HTTPS", func() {
|
ginkgo.Describe("HTTPS", func() {
|
||||||
It("proxy to HTTPS server", func() {
|
ginkgo.It("proxy to HTTPS server", func() {
|
||||||
serverConf := consts.DefaultServerConfig
|
serverConf := consts.DefaultServerConfig
|
||||||
vhostHTTPSPort := f.AllocPort()
|
vhostHTTPSPort := f.AllocPort()
|
||||||
serverConf += fmt.Sprintf(`
|
serverConf += fmt.Sprintf(`
|
||||||
@ -237,7 +237,7 @@ var _ = Describe("[Feature: Basic]", func() {
|
|||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
localServer := httpserver.New(
|
localServer := httpserver.New(
|
||||||
httpserver.WithBindPort(localPort),
|
httpserver.WithBindPort(localPort),
|
||||||
httpserver.WithTlsConfig(tlsConfig),
|
httpserver.WithTLSConfig(tlsConfig),
|
||||||
httpserver.WithResponse([]byte("test")),
|
httpserver.WithResponse([]byte("test")),
|
||||||
)
|
)
|
||||||
f.RunServer("", localServer)
|
f.RunServer("", localServer)
|
||||||
@ -275,11 +275,11 @@ var _ = Describe("[Feature: Basic]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("STCP && SUDP", func() {
|
ginkgo.Describe("STCP && SUDP", func() {
|
||||||
types := []string{"stcp", "sudp"}
|
types := []string{"stcp", "sudp"}
|
||||||
for _, t := range types {
|
for _, t := range types {
|
||||||
proxyType := t
|
proxyType := t
|
||||||
It(fmt.Sprintf("Expose echo server with %s", strings.ToUpper(proxyType)), func() {
|
ginkgo.It(fmt.Sprintf("Expose echo server with %s", strings.ToUpper(proxyType)), func() {
|
||||||
serverConf := consts.DefaultServerConfig
|
serverConf := consts.DefaultServerConfig
|
||||||
clientServerConf := consts.DefaultClientConfig
|
clientServerConf := consts.DefaultClientConfig
|
||||||
clientVisitorConf := consts.DefaultClientConfig
|
clientVisitorConf := consts.DefaultClientConfig
|
||||||
@ -381,8 +381,8 @@ var _ = Describe("[Feature: Basic]", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("TCPMUX", func() {
|
ginkgo.Describe("TCPMUX", func() {
|
||||||
It("Type tcpmux", func() {
|
ginkgo.It("Type tcpmux", func() {
|
||||||
serverConf := consts.DefaultServerConfig
|
serverConf := consts.DefaultServerConfig
|
||||||
clientConf := consts.DefaultClientConfig
|
clientConf := consts.DefaultClientConfig
|
||||||
|
|
||||||
|
@ -6,18 +6,18 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/onsi/ginkgo"
|
||||||
|
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||||
clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client"
|
clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("[Feature: ClientManage]", func() {
|
var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
||||||
f := framework.NewDefaultFramework()
|
f := framework.NewDefaultFramework()
|
||||||
|
|
||||||
It("Update && Reload API", func() {
|
ginkgo.It("Update && Reload API", func() {
|
||||||
serverConf := consts.DefaultServerConfig
|
serverConf := consts.DefaultServerConfig
|
||||||
|
|
||||||
adminPort := f.AllocPort()
|
adminPort := f.AllocPort()
|
||||||
@ -62,7 +62,9 @@ var _ = Describe("[Feature: ClientManage]", func() {
|
|||||||
// change p2 port and remove p3 proxy
|
// change p2 port and remove p3 proxy
|
||||||
newClientConf := strings.ReplaceAll(conf, strconv.Itoa(p2Port), strconv.Itoa(newP2Port))
|
newClientConf := strings.ReplaceAll(conf, strconv.Itoa(p2Port), strconv.Itoa(newP2Port))
|
||||||
p3Index := strings.Index(newClientConf, "[p3]")
|
p3Index := strings.Index(newClientConf, "[p3]")
|
||||||
newClientConf = newClientConf[:p3Index]
|
if p3Index >= 0 {
|
||||||
|
newClientConf = newClientConf[:p3Index]
|
||||||
|
}
|
||||||
|
|
||||||
err = client.UpdateConfig(newClientConf)
|
err = client.UpdateConfig(newClientConf)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
@ -77,7 +79,7 @@ var _ = Describe("[Feature: ClientManage]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(p3Port).Explain("p3 port").ExpectError(true).Ensure()
|
framework.NewRequestExpect(f).Port(p3Port).Explain("p3 port").ExpectError(true).Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
It("healthz", func() {
|
ginkgo.It("healthz", func() {
|
||||||
serverConf := consts.DefaultServerConfig
|
serverConf := consts.DefaultServerConfig
|
||||||
|
|
||||||
dashboardPort := f.AllocPort()
|
dashboardPort := f.AllocPort()
|
||||||
@ -99,5 +101,4 @@ var _ = Describe("[Feature: ClientManage]", func() {
|
|||||||
}).Port(dashboardPort).
|
}).Port(dashboardPort).
|
||||||
Ensure(framework.ExpectResponseCode(401))
|
Ensure(framework.ExpectResponseCode(401))
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -4,12 +4,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/onsi/ginkgo"
|
||||||
|
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/cert"
|
"github.com/fatedier/frp/test/e2e/pkg/cert"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type generalTestConfigures struct {
|
type generalTestConfigures struct {
|
||||||
@ -54,15 +54,15 @@ func runClientServerTest(f *framework.Framework, configures *generalTestConfigur
|
|||||||
|
|
||||||
// defineClientServerTest test a normal tcp and udp proxy with specified TestConfigures.
|
// defineClientServerTest test a normal tcp and udp proxy with specified TestConfigures.
|
||||||
func defineClientServerTest(desc string, f *framework.Framework, configures *generalTestConfigures) {
|
func defineClientServerTest(desc string, f *framework.Framework, configures *generalTestConfigures) {
|
||||||
It(desc, func() {
|
ginkgo.It(desc, func() {
|
||||||
runClientServerTest(f, configures)
|
runClientServerTest(f, configures)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = Describe("[Feature: Client-Server]", func() {
|
var _ = ginkgo.Describe("[Feature: Client-Server]", func() {
|
||||||
f := framework.NewDefaultFramework()
|
f := framework.NewDefaultFramework()
|
||||||
|
|
||||||
Describe("Protocol", func() {
|
ginkgo.Describe("Protocol", func() {
|
||||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||||
for _, protocol := range supportProtocols {
|
for _, protocol := range supportProtocols {
|
||||||
configures := &generalTestConfigures{
|
configures := &generalTestConfigures{
|
||||||
@ -76,7 +76,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Authentication", func() {
|
ginkgo.Describe("Authentication", func() {
|
||||||
defineClientServerTest("Token Correct", f, &generalTestConfigures{
|
defineClientServerTest("Token Correct", f, &generalTestConfigures{
|
||||||
server: "token = 123456",
|
server: "token = 123456",
|
||||||
client: "token = 123456",
|
client: "token = 123456",
|
||||||
@ -89,7 +89,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("TLS", func() {
|
ginkgo.Describe("TLS", func() {
|
||||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||||
for _, protocol := range supportProtocols {
|
for _, protocol := range supportProtocols {
|
||||||
tmp := protocol
|
tmp := protocol
|
||||||
@ -114,7 +114,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("TLS with custom certificate", func() {
|
ginkgo.Describe("TLS with custom certificate", func() {
|
||||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -122,7 +122,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
serverCrtPath, serverKeyPath string
|
serverCrtPath, serverKeyPath string
|
||||||
clientCrtPath, clientKeyPath string
|
clientCrtPath, clientKeyPath string
|
||||||
)
|
)
|
||||||
JustBeforeEach(func() {
|
ginkgo.JustBeforeEach(func() {
|
||||||
generator := &cert.SelfSignedCertGenerator{}
|
generator := &cert.SelfSignedCertGenerator{}
|
||||||
artifacts, err := generator.Generate("0.0.0.0")
|
artifacts, err := generator.Generate("0.0.0.0")
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
@ -131,7 +131,8 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
|
serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||||
serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
|
serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
|
||||||
generator.SetCA(artifacts.CACert, artifacts.CAKey)
|
generator.SetCA(artifacts.CACert, artifacts.CAKey)
|
||||||
generator.Generate("0.0.0.0")
|
_, err = generator.Generate("0.0.0.0")
|
||||||
|
framework.ExpectNoError(err)
|
||||||
clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
|
clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
|
||||||
clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
|
clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
|
||||||
})
|
})
|
||||||
@ -139,7 +140,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
for _, protocol := range supportProtocols {
|
for _, protocol := range supportProtocols {
|
||||||
tmp := protocol
|
tmp := protocol
|
||||||
|
|
||||||
It("one-way authentication: "+tmp, func() {
|
ginkgo.It("one-way authentication: "+tmp, func() {
|
||||||
runClientServerTest(f, &generalTestConfigures{
|
runClientServerTest(f, &generalTestConfigures{
|
||||||
server: fmt.Sprintf(`
|
server: fmt.Sprintf(`
|
||||||
protocol = %s
|
protocol = %s
|
||||||
@ -155,7 +156,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
It("mutual authentication: "+tmp, func() {
|
ginkgo.It("mutual authentication: "+tmp, func() {
|
||||||
runClientServerTest(f, &generalTestConfigures{
|
runClientServerTest(f, &generalTestConfigures{
|
||||||
server: fmt.Sprintf(`
|
server: fmt.Sprintf(`
|
||||||
protocol = %s
|
protocol = %s
|
||||||
@ -176,13 +177,13 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("TLS with custom certificate and specified server name", func() {
|
ginkgo.Describe("TLS with custom certificate and specified server name", func() {
|
||||||
var (
|
var (
|
||||||
caCrtPath string
|
caCrtPath string
|
||||||
serverCrtPath, serverKeyPath string
|
serverCrtPath, serverKeyPath string
|
||||||
clientCrtPath, clientKeyPath string
|
clientCrtPath, clientKeyPath string
|
||||||
)
|
)
|
||||||
JustBeforeEach(func() {
|
ginkgo.JustBeforeEach(func() {
|
||||||
generator := &cert.SelfSignedCertGenerator{}
|
generator := &cert.SelfSignedCertGenerator{}
|
||||||
artifacts, err := generator.Generate("example.com")
|
artifacts, err := generator.Generate("example.com")
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
@ -191,12 +192,13 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
|
serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||||
serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
|
serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
|
||||||
generator.SetCA(artifacts.CACert, artifacts.CAKey)
|
generator.SetCA(artifacts.CACert, artifacts.CAKey)
|
||||||
generator.Generate("example.com")
|
_, err = generator.Generate("example.com")
|
||||||
|
framework.ExpectNoError(err)
|
||||||
clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
|
clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
|
||||||
clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
|
clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("mutual authentication", func() {
|
ginkgo.It("mutual authentication", func() {
|
||||||
runClientServerTest(f, &generalTestConfigures{
|
runClientServerTest(f, &generalTestConfigures{
|
||||||
server: fmt.Sprintf(`
|
server: fmt.Sprintf(`
|
||||||
tls_cert_file = %s
|
tls_cert_file = %s
|
||||||
@ -213,7 +215,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
It("mutual authentication with incorrect server name", func() {
|
ginkgo.It("mutual authentication with incorrect server name", func() {
|
||||||
runClientServerTest(f, &generalTestConfigures{
|
runClientServerTest(f, &generalTestConfigures{
|
||||||
server: fmt.Sprintf(`
|
server: fmt.Sprintf(`
|
||||||
tls_cert_file = %s
|
tls_cert_file = %s
|
||||||
@ -232,7 +234,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("TLS with disable_custom_tls_first_byte", func() {
|
ginkgo.Describe("TLS with disable_custom_tls_first_byte", func() {
|
||||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||||
for _, protocol := range supportProtocols {
|
for _, protocol := range supportProtocols {
|
||||||
tmp := protocol
|
tmp := protocol
|
||||||
@ -250,7 +252,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("IPv6 bind address", func() {
|
ginkgo.Describe("IPv6 bind address", func() {
|
||||||
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
supportProtocols := []string{"tcp", "kcp", "websocket"}
|
||||||
for _, protocol := range supportProtocols {
|
for _, protocol := range supportProtocols {
|
||||||
tmp := protocol
|
tmp := protocol
|
||||||
|
@ -5,21 +5,21 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/onsi/ginkgo"
|
||||||
|
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ConfigValidStr = "syntax is ok"
|
ConfigValidStr = "syntax is ok"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("[Feature: Cmd]", func() {
|
var _ = ginkgo.Describe("[Feature: Cmd]", func() {
|
||||||
f := framework.NewDefaultFramework()
|
f := framework.NewDefaultFramework()
|
||||||
|
|
||||||
Describe("Verify", func() {
|
ginkgo.Describe("Verify", func() {
|
||||||
It("frps valid", func() {
|
ginkgo.It("frps valid", func() {
|
||||||
path := f.GenerateConfigFile(`
|
path := f.GenerateConfigFile(`
|
||||||
[common]
|
[common]
|
||||||
bind_addr = 0.0.0.0
|
bind_addr = 0.0.0.0
|
||||||
@ -29,7 +29,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
|||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output)
|
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output)
|
||||||
})
|
})
|
||||||
It("frps invalid", func() {
|
ginkgo.It("frps invalid", func() {
|
||||||
path := f.GenerateConfigFile(`
|
path := f.GenerateConfigFile(`
|
||||||
[common]
|
[common]
|
||||||
bind_addr = 0.0.0.0
|
bind_addr = 0.0.0.0
|
||||||
@ -39,7 +39,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
|||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
framework.ExpectTrue(!strings.Contains(output, ConfigValidStr), "output: %s", output)
|
framework.ExpectTrue(!strings.Contains(output, ConfigValidStr), "output: %s", output)
|
||||||
})
|
})
|
||||||
It("frpc valid", func() {
|
ginkgo.It("frpc valid", func() {
|
||||||
path := f.GenerateConfigFile(`
|
path := f.GenerateConfigFile(`
|
||||||
[common]
|
[common]
|
||||||
server_addr = 0.0.0.0
|
server_addr = 0.0.0.0
|
||||||
@ -49,7 +49,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
|||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output)
|
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output)
|
||||||
})
|
})
|
||||||
It("frpc invalid", func() {
|
ginkgo.It("frpc invalid", func() {
|
||||||
path := f.GenerateConfigFile(`
|
path := f.GenerateConfigFile(`
|
||||||
[common]
|
[common]
|
||||||
server_addr = 0.0.0.0
|
server_addr = 0.0.0.0
|
||||||
@ -62,8 +62,8 @@ var _ = Describe("[Feature: Cmd]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Single proxy", func() {
|
ginkgo.Describe("Single proxy", func() {
|
||||||
It("TCP", func() {
|
ginkgo.It("TCP", func() {
|
||||||
serverPort := f.AllocPort()
|
serverPort := f.AllocPort()
|
||||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort))
|
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort))
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
@ -77,7 +77,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(remotePort).Ensure()
|
framework.NewRequestExpect(f).Port(remotePort).Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
It("UDP", func() {
|
ginkgo.It("UDP", func() {
|
||||||
serverPort := f.AllocPort()
|
serverPort := f.AllocPort()
|
||||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort))
|
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort))
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
@ -92,7 +92,7 @@ var _ = Describe("[Feature: Cmd]", func() {
|
|||||||
Port(remotePort).Ensure()
|
Port(remotePort).Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
It("HTTP", func() {
|
ginkgo.It("HTTP", func() {
|
||||||
serverPort := f.AllocPort()
|
serverPort := f.AllocPort()
|
||||||
vhostHTTPPort := f.AllocPort()
|
vhostHTTPPort := f.AllocPort()
|
||||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost_http_port", strconv.Itoa(vhostHTTPPort))
|
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost_http_port", strconv.Itoa(vhostHTTPPort))
|
||||||
|
@ -3,18 +3,18 @@ package basic
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/onsi/ginkgo"
|
||||||
|
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("[Feature: Config]", func() {
|
var _ = ginkgo.Describe("[Feature: Config]", func() {
|
||||||
f := framework.NewDefaultFramework()
|
f := framework.NewDefaultFramework()
|
||||||
|
|
||||||
Describe("Template", func() {
|
ginkgo.Describe("Template", func() {
|
||||||
It("render by env", func() {
|
ginkgo.It("render by env", func() {
|
||||||
serverConf := consts.DefaultServerConfig
|
serverConf := consts.DefaultServerConfig
|
||||||
clientConf := consts.DefaultClientConfig
|
clientConf := consts.DefaultClientConfig
|
||||||
|
|
||||||
@ -39,8 +39,8 @@ var _ = Describe("[Feature: Config]", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Includes", func() {
|
ginkgo.Describe("Includes", func() {
|
||||||
It("split tcp proxies into different files", func() {
|
ginkgo.It("split tcp proxies into different files", func() {
|
||||||
serverPort := f.AllocPort()
|
serverPort := f.AllocPort()
|
||||||
serverConfigPath := f.GenerateConfigFile(fmt.Sprintf(`
|
serverConfigPath := f.GenerateConfigFile(fmt.Sprintf(`
|
||||||
[common]
|
[common]
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user