1
0
mirror of https://github.com/fatedier/frp.git synced 2025-05-09 16:18:27 +00:00

Merge pull request from fatedier/dev

bump version
This commit is contained in:
fatedier 2024-03-12 16:55:25 +08:00 committed by GitHub
commit 1e650ea9a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
108 changed files with 891 additions and 927 deletions

@ -2,24 +2,15 @@ version: 2
jobs:
go-version-latest:
docker:
- image: cimg/go:1.21-node
- image: cimg/go:1.22-node
resource_class: large
steps:
- checkout
- run: make
- run: make alltest
go-version-last:
docker:
- image: cimg/go:1.20-node
resource_class: large
steps:
- checkout
- run: make
- run: make alltest
- checkout
- run: make
- run: make alltest
workflows:
version: 2
build_and_test:
jobs:
- go-version-latest
- go-version-last
- go-version-latest

@ -19,15 +19,15 @@ jobs:
steps:
# environment
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: '0'
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
# get image tag name
- name: Get Image Tag Name
@ -38,13 +38,13 @@ jobs:
echo "TAG_NAME=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
fi
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Login to the GPR
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@ -72,7 +72,7 @@ jobs:
${{ env.TAG_FRPC_GPR }}
- name: Build and push frps
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: ./dockerfiles/Dockerfile-for-frps

@ -14,28 +14,29 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v4
with:
go-version: '1.21'
- 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.55
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: false
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
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.56
# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=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: 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 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 ~/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
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true

@ -8,21 +8,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: '1.22'
- name: Make All
run: |
./package.sh
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4
uses: goreleaser/goreleaser-action@v5
with:
version: latest
args: release --clean --release-notes=./Release.md

@ -1,5 +1,5 @@
service:
golangci-lint-version: 1.55.x # use the fixed version to not introduce new linters unexpectedly
golangci-lint-version: 1.56.x # use the fixed version to not introduce new linters unexpectedly
run:
concurrency: 4

@ -1,11 +1,14 @@
export PATH := $(GOPATH)/bin:$(PATH)
export PATH := $(PATH):`go env GOPATH`/bin
export GO111MODULE=on
LDFLAGS := -s -w
all: fmt build
all: env fmt build
build: frps frpc
env:
@go version
# compile assets into binary file
file:
rm -rf ./assets/frps/static/*

@ -2,6 +2,8 @@
[![Build Status](https://circleci.com/gh/fatedier/frp.svg?style=shield)](https://circleci.com/gh/fatedier/frp)
[![GitHub release](https://img.shields.io/github/tag/fatedier/frp.svg?label=release)](https://github.com/fatedier/frp/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/fatedier/frp)](https://goreportcard.com/report/github.com/fatedier/frp)
[![GitHub Releases Stats](https://img.shields.io/github/downloads/fatedier/frp/total.svg?logo=github)](https://somsubhra.github.io/github-release-stats/?username=fatedier&repository=frp)
[README](README.md) | [中文文档](README_zh.md)
@ -12,8 +14,8 @@
<img width="350px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
</a>
<a>&nbsp</a>
<a href="https://www.nango.dev?utm_source=github&utm_medium=oss-banner&utm_campaign=fatedier-frp" target="_blank">
<img width="400px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_nango.png">
<a href="https://github.com/daytonaio/daytona" target="_blank">
<img width="360px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_daytona.png">
</a>
</p>
<!--gold sponsors end-->
@ -201,11 +203,11 @@ This example implements multiple SSH services exposed through the same port usin
4. To access internal machine A using SSH ProxyCommand, assuming the username is "test":
`ssh -o 'proxycommand socat - PROXY:x.x.x.x:machine-a.example.com:22,proxyport=5002' test@machine-a`
`ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@machine-a.example.com`
5. To access internal machine B, the only difference is the domain name, assuming the username is "test":
`ssh -o 'proxycommand socat - PROXY:x.x.x.x:machine-b.example.com:22,proxyport=5002' test@machine-b`
`ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@machine-b.example.com`
### Accessing Internal Web Services with Custom Domains in LAN
@ -526,6 +528,8 @@ Check frp's status and proxies' statistics information by Dashboard.
Configure a port for dashboard to enable this feature:
```toml
# The default value is 127.0.0.1. Change it to 0.0.0.0 when you want to access it from a public network.
webServer.addr = "0.0.0.0"
webServer.port = 7500
# dashboard's username and password are both optional
webServer.user = "admin"

@ -2,6 +2,8 @@
[![Build Status](https://circleci.com/gh/fatedier/frp.svg?style=shield)](https://circleci.com/gh/fatedier/frp)
[![GitHub release](https://img.shields.io/github/tag/fatedier/frp.svg?label=release)](https://github.com/fatedier/frp/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/fatedier/frp)](https://goreportcard.com/report/github.com/fatedier/frp)
[![GitHub Releases Stats](https://img.shields.io/github/downloads/fatedier/frp/total.svg?logo=github)](https://somsubhra.github.io/github-release-stats/?username=fatedier&repository=frp)
[README](README.md) | [中文文档](README_zh.md)
@ -14,8 +16,8 @@ frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP
<img width="350px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
</a>
<a>&nbsp</a>
<a href="https://www.nango.dev?utm_source=github&utm_medium=oss-banner&utm_campaign=fatedier-frp" target="_blank">
<img width="400px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_nango.png">
<a href="https://github.com/daytonaio/daytona" target="_blank">
<img width="360px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_daytona.png">
</a>
</p>
<!--gold sponsors end-->

@ -1,11 +1,12 @@
### Deprecation Notices
### Notable Changes
* Using an underscore in a flag name is deprecated and has been replaced by a hyphen. The underscore format will remain compatible for some time, until it is completely removed in a future version. For example, `--remote_port` is replaced with `--remote-port`.
* The minimum supported Go version has been updated to `1.22`. In the new version of Go, the default minimum supported TLS version has been changed to `TLS 1.2`.
* The default value of `--strict-config` has been changed from `false` to `true`. If your configuration file uses a non-existent configuration item or has a spelling error, the application will throw an error. This startup parameter was introduced in version `v0.53.0`. If you wish to continue using the old behavior, you need to explicitly set `--strict-config=false`.
### Features
* The `Refresh` and `ClearOfflineProxies` buttons have been added to the Dashboard of frps.
* Proxy supports configuring annotations, which will be displayed in the frps dashboard.
### Fixes
### Changes
* The host/domain matching in the routing rules has been changed to be case-insensitive.
* Removed dependencies on the forked version of kcp-go and beego log, kcp-go now uses the upstream version, and golib/log replaces beego log.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>frps dashboard</title>
<script type="module" crossorigin src="./index-1gecbKzv.js"></script>
<link rel="stylesheet" crossorigin href="./index-Lf6B06jY.css">
<script type="module" crossorigin src="./index-Q42Pu2_S.js"></script>
<link rel="stylesheet" crossorigin href="./index-rzPDshRD.css">
</head>
<body>

@ -15,19 +15,17 @@
package client
import (
"cmp"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
"sort"
"slices"
"strconv"
"strings"
"time"
"github.com/samber/lo"
"github.com/fatedier/frp/client/proxy"
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/config/v1/validation"
@ -78,9 +76,9 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
strictConfigMode, _ = strconv.ParseBool(strictStr)
}
log.Info("api request [/api/reload]")
log.Infof("api request [/api/reload]")
defer func() {
log.Info("api response [/api/reload], code [%d]", res.Code)
log.Infof("api response [/api/reload], code [%d]", res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
@ -91,32 +89,32 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
if err != nil {
res.Code = 400
res.Msg = err.Error()
log.Warn("reload frpc proxy config error: %s", res.Msg)
log.Warnf("reload frpc proxy config error: %s", res.Msg)
return
}
if _, err := validation.ValidateAllClientConfig(cliCfg, proxyCfgs, visitorCfgs); err != nil {
res.Code = 400
res.Msg = err.Error()
log.Warn("reload frpc proxy config error: %s", res.Msg)
log.Warnf("reload frpc proxy config error: %s", res.Msg)
return
}
if err := svr.UpdateAllConfigurer(proxyCfgs, visitorCfgs); err != nil {
res.Code = 500
res.Msg = err.Error()
log.Warn("reload frpc proxy config error: %s", res.Msg)
log.Warnf("reload frpc proxy config error: %s", res.Msg)
return
}
log.Info("success reload conf")
log.Infof("success reload conf")
}
// POST /api/stop
func (svr *Service) apiStop(w http.ResponseWriter, _ *http.Request) {
res := GeneralResponse{Code: 200}
log.Info("api request [/api/stop]")
log.Infof("api request [/api/stop]")
defer func() {
log.Info("api response [/api/stop], code [%d]", res.Code)
log.Infof("api response [/api/stop], code [%d]", res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
@ -153,7 +151,7 @@ func NewProxyStatusResp(status *proxy.WorkingStatus, serverAddr string) ProxySta
if status.Err == "" {
psr.RemoteAddr = status.RemoteAddr
if lo.Contains([]string{"tcp", "udp"}, status.Type) {
if slices.Contains([]string{"tcp", "udp"}, status.Type) {
psr.RemoteAddr = serverAddr + psr.RemoteAddr
}
}
@ -167,9 +165,9 @@ func (svr *Service) apiStatus(w http.ResponseWriter, _ *http.Request) {
res StatusResp = make(map[string][]ProxyStatusResp)
)
log.Info("Http request [/api/status]")
log.Infof("Http request [/api/status]")
defer func() {
log.Info("Http response [/api/status]")
log.Infof("Http response [/api/status]")
buf, _ = json.Marshal(&res)
_, _ = w.Write(buf)
}()
@ -190,8 +188,8 @@ func (svr *Service) apiStatus(w http.ResponseWriter, _ *http.Request) {
if len(arrs) <= 1 {
continue
}
sort.Slice(arrs, func(i, j int) bool {
return strings.Compare(arrs[i].Name, arrs[j].Name) < 0
slices.SortFunc(arrs, func(a, b ProxyStatusResp) int {
return cmp.Compare(a.Name, b.Name)
})
}
}
@ -200,9 +198,9 @@ func (svr *Service) apiStatus(w http.ResponseWriter, _ *http.Request) {
func (svr *Service) apiGetConfig(w http.ResponseWriter, _ *http.Request) {
res := GeneralResponse{Code: 200}
log.Info("Http get request [/api/config]")
log.Infof("Http get request [/api/config]")
defer func() {
log.Info("Http get response [/api/config], code [%d]", res.Code)
log.Infof("Http get response [/api/config], code [%d]", res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
@ -212,7 +210,7 @@ func (svr *Service) apiGetConfig(w http.ResponseWriter, _ *http.Request) {
if svr.configFilePath == "" {
res.Code = 400
res.Msg = "frpc has no config file path"
log.Warn("%s", res.Msg)
log.Warnf("%s", res.Msg)
return
}
@ -220,7 +218,7 @@ func (svr *Service) apiGetConfig(w http.ResponseWriter, _ *http.Request) {
if err != nil {
res.Code = 400
res.Msg = err.Error()
log.Warn("load frpc config file error: %s", res.Msg)
log.Warnf("load frpc config file error: %s", res.Msg)
return
}
res.Msg = string(content)
@ -230,9 +228,9 @@ func (svr *Service) apiGetConfig(w http.ResponseWriter, _ *http.Request) {
func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
res := GeneralResponse{Code: 200}
log.Info("Http put request [/api/config]")
log.Infof("Http put request [/api/config]")
defer func() {
log.Info("Http put response [/api/config], code [%d]", res.Code)
log.Infof("Http put response [/api/config], code [%d]", res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
@ -244,21 +242,21 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
if err != nil {
res.Code = 400
res.Msg = fmt.Sprintf("read request body error: %v", err)
log.Warn("%s", res.Msg)
log.Warnf("%s", res.Msg)
return
}
if len(body) == 0 {
res.Code = 400
res.Msg = "body can't be empty"
log.Warn("%s", res.Msg)
log.Warnf("%s", res.Msg)
return
}
if err := os.WriteFile(svr.configFilePath, body, 0o644); err != nil {
res.Code = 500
res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
log.Warn("%s", res.Msg)
log.Warnf("%s", res.Msg)
return
}
}

@ -84,7 +84,7 @@ func (c *defaultConnectorImpl) Open() error {
tlsConfig, err = transport.NewClientTLSConfig("", "", "", sn)
}
if err != nil {
xl.Warn("fail to build tls configuration, err: %v", err)
xl.Warnf("fail to build tls configuration, err: %v", err)
return err
}
tlsConfig.NextProtos = []string{"frp"}
@ -164,14 +164,14 @@ func (c *defaultConnectorImpl) realConnect() (net.Conn, error) {
c.cfg.Transport.TLS.TrustedCaFile,
sn)
if err != nil {
xl.Warn("fail to build tls configuration, err: %v", err)
xl.Warnf("fail to build tls configuration, err: %v", err)
return nil, err
}
}
proxyType, addr, auth, err := libdial.ParseProxyURL(c.cfg.Transport.ProxyURL)
if err != nil {
xl.Error("fail to parse proxy url")
xl.Errorf("fail to parse proxy url")
return nil, err
}
dialOptions := []libdial.DialOption{}

@ -124,7 +124,7 @@ func (ctl *Control) handleReqWorkConn(_ msg.Message) {
xl := ctl.xl
workConn, err := ctl.connectServer()
if err != nil {
xl.Warn("start new connection to server error: %v", err)
xl.Warnf("start new connection to server error: %v", err)
return
}
@ -132,24 +132,24 @@ func (ctl *Control) handleReqWorkConn(_ msg.Message) {
RunID: ctl.sessionCtx.RunID,
}
if err = ctl.sessionCtx.AuthSetter.SetNewWorkConn(m); err != nil {
xl.Warn("error during NewWorkConn authentication: %v", err)
xl.Warnf("error during NewWorkConn authentication: %v", err)
workConn.Close()
return
}
if err = msg.WriteMsg(workConn, m); err != nil {
xl.Warn("work connection write to server error: %v", err)
xl.Warnf("work connection write to server error: %v", err)
workConn.Close()
return
}
var startMsg msg.StartWorkConn
if err = msg.ReadMsgInto(workConn, &startMsg); err != nil {
xl.Trace("work connection closed before response StartWorkConn message: %v", err)
xl.Tracef("work connection closed before response StartWorkConn message: %v", err)
workConn.Close()
return
}
if startMsg.Error != "" {
xl.Error("StartWorkConn contains error: %s", startMsg.Error)
xl.Errorf("StartWorkConn contains error: %s", startMsg.Error)
workConn.Close()
return
}
@ -165,9 +165,9 @@ func (ctl *Control) handleNewProxyResp(m msg.Message) {
// Start a new proxy handler if no error got
err := ctl.pm.StartProxy(inMsg.ProxyName, inMsg.RemoteAddr, inMsg.Error)
if err != nil {
xl.Warn("[%s] start error: %v", inMsg.ProxyName, err)
xl.Warnf("[%s] start error: %v", inMsg.ProxyName, err)
} else {
xl.Info("[%s] start proxy success", inMsg.ProxyName)
xl.Infof("[%s] start proxy success", inMsg.ProxyName)
}
}
@ -178,7 +178,7 @@ func (ctl *Control) handleNatHoleResp(m msg.Message) {
// Dispatch the NatHoleResp message to the related proxy.
ok := ctl.msgTransporter.DispatchWithType(inMsg, msg.TypeNameNatHoleResp, inMsg.TransactionID)
if !ok {
xl.Trace("dispatch NatHoleResp message to related proxy error")
xl.Tracef("dispatch NatHoleResp message to related proxy error")
}
}
@ -187,12 +187,12 @@ func (ctl *Control) handlePong(m msg.Message) {
inMsg := m.(*msg.Pong)
if inMsg.Error != "" {
xl.Error("Pong message contains error: %s", inMsg.Error)
xl.Errorf("Pong message contains error: %s", inMsg.Error)
ctl.closeSession()
return
}
ctl.lastPong.Store(time.Now())
xl.Debug("receive heartbeat from server")
xl.Debugf("receive heartbeat from server")
}
// closeSession closes the control connection.
@ -241,10 +241,10 @@ func (ctl *Control) heartbeatWorker() {
if ctl.sessionCtx.Common.Transport.HeartbeatInterval > 0 {
// send heartbeat to server
sendHeartBeat := func() (bool, error) {
xl.Debug("send heartbeat to server")
xl.Debugf("send heartbeat to server")
pingMsg := &msg.Ping{}
if err := ctl.sessionCtx.AuthSetter.SetPing(pingMsg); err != nil {
xl.Warn("error during ping authentication: %v, skip sending ping message", err)
xl.Warnf("error during ping authentication: %v, skip sending ping message", err)
return false, err
}
_ = ctl.msgDispatcher.Send(pingMsg)
@ -269,7 +269,7 @@ func (ctl *Control) heartbeatWorker() {
go wait.Until(func() {
if time.Since(ctl.lastPong.Load().(time.Time)) > time.Duration(ctl.sessionCtx.Common.Transport.HeartbeatTimeout)*time.Second {
xl.Warn("heartbeat timeout")
xl.Warnf("heartbeat timeout")
ctl.closeSession()
return
}

@ -112,17 +112,17 @@ func (monitor *Monitor) checkWorker() {
}
if err == nil {
xl.Trace("do one health check success")
xl.Tracef("do one health check success")
if !monitor.statusOK && monitor.statusNormalFn != nil {
xl.Info("health check status change to success")
xl.Infof("health check status change to success")
monitor.statusOK = true
monitor.statusNormalFn()
}
} else {
xl.Warn("do one health check failed: %v", err)
xl.Warnf("do one health check failed: %v", err)
monitor.failedTimes++
if monitor.statusOK && int(monitor.failedTimes) >= monitor.maxFailedTimes && monitor.statusFailedFn != nil {
xl.Warn("health check status change to failed")
xl.Warnf("health check status change to failed")
monitor.statusOK = false
monitor.statusFailedFn()
}

@ -141,13 +141,13 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor
})
}
xl.Trace("handle tcp work connection, useEncryption: %t, useCompression: %t",
xl.Tracef("handle tcp work connection, useEncryption: %t, useCompression: %t",
baseCfg.Transport.UseEncryption, baseCfg.Transport.UseCompression)
if baseCfg.Transport.UseEncryption {
remote, err = libio.WithEncryption(remote, encKey)
if err != nil {
workConn.Close()
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
return
}
}
@ -189,9 +189,9 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor
if pxy.proxyPlugin != nil {
// if plugin is set, let plugin handle connection first
xl.Debug("handle by plugin: %s", pxy.proxyPlugin.Name())
xl.Debugf("handle by plugin: %s", pxy.proxyPlugin.Name())
pxy.proxyPlugin.Handle(remote, workConn, &extraInfo)
xl.Debug("handle by plugin finished")
xl.Debugf("handle by plugin finished")
return
}
@ -201,25 +201,25 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor
)
if err != nil {
workConn.Close()
xl.Error("connect to local service [%s:%d] error: %v", baseCfg.LocalIP, baseCfg.LocalPort, err)
xl.Errorf("connect to local service [%s:%d] error: %v", baseCfg.LocalIP, baseCfg.LocalPort, err)
return
}
xl.Debug("join connections, localConn(l[%s] r[%s]) workConn(l[%s] r[%s])", localConn.LocalAddr().String(),
xl.Debugf("join connections, localConn(l[%s] r[%s]) workConn(l[%s] r[%s])", localConn.LocalAddr().String(),
localConn.RemoteAddr().String(), workConn.LocalAddr().String(), workConn.RemoteAddr().String())
if extraInfo.ProxyProtocolHeader != nil {
if _, err := extraInfo.ProxyProtocolHeader.WriteTo(localConn); err != nil {
workConn.Close()
xl.Error("write proxy protocol header to local conn error: %v", err)
xl.Errorf("write proxy protocol header to local conn error: %v", err)
return
}
}
_, _, errs := libio.Join(localConn, remote)
xl.Debug("join connections closed")
xl.Debugf("join connections closed")
if len(errs) > 0 {
xl.Trace("join connections errors: %v", errs)
xl.Tracef("join connections errors: %v", errs)
}
if compressionResourceRecycleFn != nil {
compressionResourceRecycleFn()

@ -152,7 +152,7 @@ func (pm *Manager) UpdateAll(proxyCfgs []v1.ProxyConfigurer) {
}
}
if len(delPxyNames) > 0 {
xl.Info("proxy removed: %s", delPxyNames)
xl.Infof("proxy removed: %s", delPxyNames)
}
addPxyNames := make([]string, 0)
@ -170,6 +170,6 @@ func (pm *Manager) UpdateAll(proxyCfgs []v1.ProxyConfigurer) {
}
}
if len(addPxyNames) > 0 {
xl.Info("proxy added: %s", addPxyNames)
xl.Infof("proxy added: %s", addPxyNames)
}
}

@ -114,7 +114,7 @@ func NewWrapper(
addr := net.JoinHostPort(baseInfo.LocalIP, strconv.Itoa(baseInfo.LocalPort))
pw.monitor = health.NewMonitor(pw.ctx, baseInfo.HealthCheck, addr,
pw.statusNormalCallback, pw.statusFailedCallback)
xl.Trace("enable health check monitor")
xl.Tracef("enable health check monitor")
}
pw.pxy = NewProxy(pw.ctx, pw.Cfg, clientCfg, pw.msgTransporter)
@ -197,7 +197,7 @@ func (pw *Wrapper) checkWorker() {
(pw.Phase == ProxyPhaseWaitStart && now.After(pw.lastSendStartMsg.Add(waitResponseTimeout))) ||
(pw.Phase == ProxyPhaseStartErr && now.After(pw.lastStartErr.Add(startErrTimeout))) {
xl.Trace("change status from [%s] to [%s]", pw.Phase, ProxyPhaseWaitStart)
xl.Tracef("change status from [%s] to [%s]", pw.Phase, ProxyPhaseWaitStart)
pw.Phase = ProxyPhaseWaitStart
var newProxyMsg msg.NewProxy
@ -212,7 +212,7 @@ func (pw *Wrapper) checkWorker() {
pw.mu.Lock()
if pw.Phase == ProxyPhaseRunning || pw.Phase == ProxyPhaseWaitStart {
pw.close()
xl.Trace("change status from [%s] to [%s]", pw.Phase, ProxyPhaseCheckFailed)
xl.Tracef("change status from [%s] to [%s]", pw.Phase, ProxyPhaseCheckFailed)
pw.Phase = ProxyPhaseCheckFailed
}
pw.mu.Unlock()
@ -236,7 +236,7 @@ func (pw *Wrapper) statusNormalCallback() {
default:
}
})
xl.Info("health check success")
xl.Infof("health check success")
}
func (pw *Wrapper) statusFailedCallback() {
@ -248,7 +248,7 @@ func (pw *Wrapper) statusFailedCallback() {
default:
}
})
xl.Info("health check failed")
xl.Infof("health check failed")
}
func (pw *Wrapper) InWorkConn(workConn net.Conn, m *msg.StartWorkConn) {
@ -257,7 +257,7 @@ func (pw *Wrapper) InWorkConn(workConn net.Conn, m *msg.StartWorkConn) {
pxy := pw.pxy
pw.mu.RUnlock()
if pxy != nil && pw.Phase == ProxyPhaseRunning {
xl.Debug("start a new work connection, localAddr: %s remoteAddr: %s", workConn.LocalAddr().String(), workConn.RemoteAddr().String())
xl.Debugf("start a new work connection, localAddr: %s remoteAddr: %s", workConn.LocalAddr().String(), workConn.RemoteAddr().String())
go pxy.InWorkConn(workConn, m)
} else {
workConn.Close()

@ -81,7 +81,7 @@ func (pxy *SUDPProxy) Close() {
func (pxy *SUDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
xl := pxy.xl
xl.Info("incoming a new work connection for sudp proxy, %s", conn.RemoteAddr().String())
xl.Infof("incoming a new work connection for sudp proxy, %s", conn.RemoteAddr().String())
var rwc io.ReadWriteCloser = conn
var err error
@ -94,7 +94,7 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
rwc, err = libio.WithEncryption(rwc, []byte(pxy.clientCfg.Auth.Token))
if err != nil {
conn.Close()
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
return
}
}
@ -133,21 +133,21 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
// first to check sudp proxy is closed or not
select {
case <-pxy.closeCh:
xl.Trace("frpc sudp proxy is closed")
xl.Tracef("frpc sudp proxy is closed")
return
default:
}
var udpMsg msg.UDPPacket
if errRet := msg.ReadMsgInto(conn, &udpMsg); errRet != nil {
xl.Warn("read from workConn for sudp error: %v", errRet)
xl.Warnf("read from workConn for sudp error: %v", errRet)
return
}
if errRet := errors.PanicToError(func() {
readCh <- &udpMsg
}); errRet != nil {
xl.Warn("reader goroutine for sudp work connection closed: %v", errRet)
xl.Warnf("reader goroutine for sudp work connection closed: %v", errRet)
return
}
}
@ -157,21 +157,21 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
workConnSenderFn := func(conn net.Conn, sendCh chan msg.Message) {
defer func() {
closeFn()
xl.Info("writer goroutine for sudp work connection closed")
xl.Infof("writer goroutine for sudp work connection closed")
}()
var errRet error
for rawMsg := range sendCh {
switch m := rawMsg.(type) {
case *msg.UDPPacket:
xl.Trace("frpc send udp package to frpc visitor, [udp local: %v, remote: %v], [tcp work conn local: %v, remote: %v]",
xl.Tracef("frpc send udp package to frpc visitor, [udp local: %v, remote: %v], [tcp work conn local: %v, remote: %v]",
m.LocalAddr.String(), m.RemoteAddr.String(), conn.LocalAddr().String(), conn.RemoteAddr().String())
case *msg.Ping:
xl.Trace("frpc send ping message to frpc visitor")
xl.Tracef("frpc send ping message to frpc visitor")
}
if errRet = msg.WriteMsg(conn, rawMsg); errRet != nil {
xl.Error("sudp work write error: %v", errRet)
xl.Errorf("sudp work write error: %v", errRet)
return
}
}
@ -191,11 +191,11 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
if errRet = errors.PanicToError(func() {
sendCh <- &msg.Ping{}
}); errRet != nil {
xl.Warn("heartbeat goroutine for sudp work connection closed")
xl.Warnf("heartbeat goroutine for sudp work connection closed")
return
}
case <-pxy.closeCh:
xl.Trace("frpc sudp proxy is closed")
xl.Tracef("frpc sudp proxy is closed")
return
}
}

@ -90,7 +90,7 @@ func (pxy *UDPProxy) Close() {
func (pxy *UDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
xl := pxy.xl
xl.Info("incoming a new work connection for udp proxy, %s", conn.RemoteAddr().String())
xl.Infof("incoming a new work connection for udp proxy, %s", conn.RemoteAddr().String())
// close resources related with old workConn
pxy.Close()
@ -105,7 +105,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
rwc, err = libio.WithEncryption(rwc, []byte(pxy.clientCfg.Auth.Token))
if err != nil {
conn.Close()
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
return
}
}
@ -125,32 +125,32 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
for {
var udpMsg msg.UDPPacket
if errRet := msg.ReadMsgInto(conn, &udpMsg); errRet != nil {
xl.Warn("read from workConn for udp error: %v", errRet)
xl.Warnf("read from workConn for udp error: %v", errRet)
return
}
if errRet := errors.PanicToError(func() {
xl.Trace("get udp package from workConn: %s", udpMsg.Content)
xl.Tracef("get udp package from workConn: %s", udpMsg.Content)
readCh <- &udpMsg
}); errRet != nil {
xl.Info("reader goroutine for udp work connection closed: %v", errRet)
xl.Infof("reader goroutine for udp work connection closed: %v", errRet)
return
}
}
}
workConnSenderFn := func(conn net.Conn, sendCh chan msg.Message) {
defer func() {
xl.Info("writer goroutine for udp work connection closed")
xl.Infof("writer goroutine for udp work connection closed")
}()
var errRet error
for rawMsg := range sendCh {
switch m := rawMsg.(type) {
case *msg.UDPPacket:
xl.Trace("send udp package to workConn: %s", m.Content)
xl.Tracef("send udp package to workConn: %s", m.Content)
case *msg.Ping:
xl.Trace("send ping message to udp workConn")
xl.Tracef("send ping message to udp workConn")
}
if errRet = msg.WriteMsg(conn, rawMsg); errRet != nil {
xl.Error("udp work write error: %v", errRet)
xl.Errorf("udp work write error: %v", errRet)
return
}
}
@ -162,7 +162,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
if errRet = errors.PanicToError(func() {
sendCh <- &msg.Ping{}
}); errRet != nil {
xl.Trace("heartbeat goroutine for udp work connection closed")
xl.Tracef("heartbeat goroutine for udp work connection closed")
break
}
}

@ -59,17 +59,17 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, startWorkConnMsg *msg.StartWorkC
var natHoleSidMsg msg.NatHoleSid
err := msg.ReadMsgInto(conn, &natHoleSidMsg)
if err != nil {
xl.Error("xtcp read from workConn error: %v", err)
xl.Errorf("xtcp read from workConn error: %v", err)
return
}
xl.Trace("nathole prepare start")
xl.Tracef("nathole prepare start")
prepareResult, err := nathole.Prepare([]string{pxy.clientCfg.NatHoleSTUNServer})
if err != nil {
xl.Warn("nathole prepare error: %v", err)
xl.Warnf("nathole prepare error: %v", err)
return
}
xl.Info("nathole prepare success, nat type: %s, behavior: %s, addresses: %v, assistedAddresses: %v",
xl.Infof("nathole prepare success, nat type: %s, behavior: %s, addresses: %v, assistedAddresses: %v",
prepareResult.NatType, prepareResult.Behavior, prepareResult.Addrs, prepareResult.AssistedAddrs)
defer prepareResult.ListenConn.Close()
@ -83,14 +83,14 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, startWorkConnMsg *msg.StartWorkC
AssistedAddrs: prepareResult.AssistedAddrs,
}
xl.Trace("nathole exchange info start")
xl.Tracef("nathole exchange info start")
natHoleRespMsg, err := nathole.ExchangeInfo(pxy.ctx, pxy.msgTransporter, transactionID, natHoleClientMsg, 5*time.Second)
if err != nil {
xl.Warn("nathole exchange info error: %v", err)
xl.Warnf("nathole exchange info error: %v", err)
return
}
xl.Info("get natHoleRespMsg, sid [%s], protocol [%s], candidate address %v, assisted address %v, detectBehavior: %+v",
xl.Infof("get natHoleRespMsg, sid [%s], protocol [%s], candidate address %v, assisted address %v, detectBehavior: %+v",
natHoleRespMsg.Sid, natHoleRespMsg.Protocol, natHoleRespMsg.CandidateAddrs,
natHoleRespMsg.AssistedAddrs, natHoleRespMsg.DetectBehavior)
@ -98,7 +98,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, startWorkConnMsg *msg.StartWorkC
newListenConn, raddr, err := nathole.MakeHole(pxy.ctx, listenConn, natHoleRespMsg, []byte(pxy.cfg.Secretkey))
if err != nil {
listenConn.Close()
xl.Warn("make hole error: %v", err)
xl.Warnf("make hole error: %v", err)
_ = pxy.msgTransporter.Send(&msg.NatHoleReport{
Sid: natHoleRespMsg.Sid,
Success: false,
@ -106,7 +106,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, startWorkConnMsg *msg.StartWorkC
return
}
listenConn = newListenConn
xl.Info("establishing nat hole connection successful, sid [%s], remoteAddr [%s]", natHoleRespMsg.Sid, raddr)
xl.Infof("establishing nat hole connection successful, sid [%s], remoteAddr [%s]", natHoleRespMsg.Sid, raddr)
_ = pxy.msgTransporter.Send(&msg.NatHoleReport{
Sid: natHoleRespMsg.Sid,
@ -128,14 +128,14 @@ func (pxy *XTCPProxy) listenByKCP(listenConn *net.UDPConn, raddr *net.UDPAddr, s
laddr, _ := net.ResolveUDPAddr("udp", listenConn.LocalAddr().String())
lConn, err := net.DialUDP("udp", laddr, raddr)
if err != nil {
xl.Warn("dial udp error: %v", err)
xl.Warnf("dial udp error: %v", err)
return
}
defer lConn.Close()
remote, err := netpkg.NewKCPConnFromUDP(lConn, true, raddr.String())
if err != nil {
xl.Warn("create kcp connection from udp connection error: %v", err)
xl.Warnf("create kcp connection from udp connection error: %v", err)
return
}
@ -145,7 +145,7 @@ func (pxy *XTCPProxy) listenByKCP(listenConn *net.UDPConn, raddr *net.UDPAddr, s
fmuxCfg.LogOutput = io.Discard
session, err := fmux.Server(remote, fmuxCfg)
if err != nil {
xl.Error("create mux session error: %v", err)
xl.Errorf("create mux session error: %v", err)
return
}
defer session.Close()
@ -153,7 +153,7 @@ func (pxy *XTCPProxy) listenByKCP(listenConn *net.UDPConn, raddr *net.UDPAddr, s
for {
muxConn, err := session.Accept()
if err != nil {
xl.Error("accept connection error: %v", err)
xl.Errorf("accept connection error: %v", err)
return
}
go pxy.HandleTCPWorkConnection(muxConn, startWorkConnMsg, []byte(pxy.cfg.Secretkey))
@ -166,7 +166,7 @@ func (pxy *XTCPProxy) listenByQUIC(listenConn *net.UDPConn, _ *net.UDPAddr, star
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
if err != nil {
xl.Warn("create tls config error: %v", err)
xl.Warnf("create tls config error: %v", err)
return
}
tlsConfig.NextProtos = []string{"frp"}
@ -178,19 +178,19 @@ func (pxy *XTCPProxy) listenByQUIC(listenConn *net.UDPConn, _ *net.UDPAddr, star
},
)
if err != nil {
xl.Warn("dial quic error: %v", err)
xl.Warnf("dial quic error: %v", err)
return
}
// only accept one connection from raddr
c, err := quicListener.Accept(pxy.ctx)
if err != nil {
xl.Error("quic accept connection error: %v", err)
xl.Errorf("quic accept connection error: %v", err)
return
}
for {
stream, err := c.AcceptStream(pxy.ctx)
if err != nil {
xl.Debug("quic accept stream error: %v", err)
xl.Debugf("quic accept stream error: %v", err)
_ = c.CloseWithError(0, "")
return
}

@ -174,9 +174,9 @@ func (svr *Service) Run(ctx context.Context) error {
if svr.webServer != nil {
go func() {
log.Info("admin server listen on %s", svr.webServer.Address())
log.Infof("admin server listen on %s", svr.webServer.Address())
if err := svr.webServer.Run(); err != nil {
log.Warn("admin server exit with error: %v", err)
log.Warnf("admin server exit with error: %v", err)
}
}()
}
@ -269,14 +269,14 @@ func (svr *Service) login() (conn net.Conn, connector Connector, err error) {
if loginRespMsg.Error != "" {
err = fmt.Errorf("%s", loginRespMsg.Error)
xl.Error("%s", loginRespMsg.Error)
xl.Errorf("%s", loginRespMsg.Error)
return
}
svr.runID = loginRespMsg.RunID
xl.AddPrefix(xlog.LogPrefix{Name: "runID", Value: svr.runID})
xl.Info("login to server success, get run id [%s]", loginRespMsg.RunID)
xl.Infof("login to server success, get run id [%s]", loginRespMsg.RunID)
return
}
@ -284,10 +284,10 @@ func (svr *Service) loopLoginUntilSuccess(maxInterval time.Duration, firstLoginE
xl := xlog.FromContextSafe(svr.ctx)
loginFunc := func() (bool, error) {
xl.Info("try to connect to server...")
xl.Infof("try to connect to server...")
conn, connector, err := svr.login()
if err != nil {
xl.Warn("connect to server error: %v", err)
xl.Warnf("connect to server error: %v", err)
if firstLoginExit {
svr.cancel(cancelErr{Err: err})
}
@ -313,7 +313,7 @@ func (svr *Service) loopLoginUntilSuccess(maxInterval time.Duration, firstLoginE
ctl, err := NewControl(svr.ctx, sessionCtx)
if err != nil {
conn.Close()
xl.Error("NewControl error: %v", err)
xl.Errorf("NewControl error: %v", err)
return false, err
}
ctl.SetInWorkConnCallback(svr.handleWorkConnCb)

@ -56,7 +56,7 @@ func (sv *STCPVisitor) worker() {
for {
conn, err := sv.l.Accept()
if err != nil {
xl.Warn("stcp local listener closed")
xl.Warnf("stcp local listener closed")
return
}
go sv.handleConn(conn)
@ -68,7 +68,7 @@ func (sv *STCPVisitor) internalConnWorker() {
for {
conn, err := sv.internalLn.Accept()
if err != nil {
xl.Warn("stcp internal listener closed")
xl.Warnf("stcp internal listener closed")
return
}
go sv.handleConn(conn)
@ -79,7 +79,7 @@ func (sv *STCPVisitor) handleConn(userConn net.Conn) {
xl := xlog.FromContextSafe(sv.ctx)
defer userConn.Close()
xl.Debug("get a new stcp user connection")
xl.Debugf("get a new stcp user connection")
visitorConn, err := sv.helper.ConnectServer()
if err != nil {
return
@ -97,7 +97,7 @@ func (sv *STCPVisitor) handleConn(userConn net.Conn) {
}
err = msg.WriteMsg(visitorConn, newVisitorConnMsg)
if err != nil {
xl.Warn("send newVisitorConnMsg to server error: %v", err)
xl.Warnf("send newVisitorConnMsg to server error: %v", err)
return
}
@ -105,13 +105,13 @@ func (sv *STCPVisitor) handleConn(userConn net.Conn) {
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
if err != nil {
xl.Warn("get newVisitorConnRespMsg error: %v", err)
xl.Warnf("get newVisitorConnRespMsg error: %v", err)
return
}
_ = visitorConn.SetReadDeadline(time.Time{})
if newVisitorConnRespMsg.Error != "" {
xl.Warn("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
xl.Warnf("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
return
}
@ -120,7 +120,7 @@ func (sv *STCPVisitor) handleConn(userConn net.Conn) {
if sv.cfg.Transport.UseEncryption {
remote, err = libio.WithEncryption(remote, []byte(sv.cfg.SecretKey))
if err != nil {
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
return
}
}

@ -62,7 +62,7 @@ func (sv *SUDPVisitor) Run() (err error) {
sv.sendCh = make(chan *msg.UDPPacket, 1024)
sv.readCh = make(chan *msg.UDPPacket, 1024)
xl.Info("sudp start to work, listen on %s", addr)
xl.Infof("sudp start to work, listen on %s", addr)
go sv.dispatcher()
go udp.ForwardUserConn(sv.udpConn, sv.readCh, sv.sendCh, int(sv.clientCfg.UDPPacketSize))
@ -84,17 +84,17 @@ func (sv *SUDPVisitor) dispatcher() {
select {
case firstPacket = <-sv.sendCh:
if firstPacket == nil {
xl.Info("frpc sudp visitor proxy is closed")
xl.Infof("frpc sudp visitor proxy is closed")
return
}
case <-sv.checkCloseCh:
xl.Info("frpc sudp visitor proxy is closed")
xl.Infof("frpc sudp visitor proxy is closed")
return
}
visitorConn, err = sv.getNewVisitorConn()
if err != nil {
xl.Warn("newVisitorConn to frps error: %v, try to reconnect", err)
xl.Warnf("newVisitorConn to frps error: %v, try to reconnect", err)
continue
}
@ -111,7 +111,7 @@ func (sv *SUDPVisitor) dispatcher() {
func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
xl := xlog.FromContextSafe(sv.ctx)
xl.Debug("starting sudp proxy worker")
xl.Debugf("starting sudp proxy worker")
wg := &sync.WaitGroup{}
wg.Add(2)
@ -134,21 +134,21 @@ func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
// frpc will send heartbeat in workConn to frpc visitor for keeping alive
_ = conn.SetReadDeadline(time.Now().Add(60 * time.Second))
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
xl.Warn("read from workconn for user udp conn error: %v", errRet)
xl.Warnf("read from workconn for user udp conn error: %v", errRet)
return
}
_ = conn.SetReadDeadline(time.Time{})
switch m := rawMsg.(type) {
case *msg.Ping:
xl.Debug("frpc visitor get ping message from frpc")
xl.Debugf("frpc visitor get ping message from frpc")
continue
case *msg.UDPPacket:
if errRet := errors.PanicToError(func() {
sv.readCh <- m
xl.Trace("frpc visitor get udp packet from workConn: %s", m.Content)
xl.Tracef("frpc visitor get udp packet from workConn: %s", m.Content)
}); errRet != nil {
xl.Info("reader goroutine for udp work connection closed")
xl.Infof("reader goroutine for udp work connection closed")
return
}
}
@ -165,25 +165,25 @@ func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
var errRet error
if firstPacket != nil {
if errRet = msg.WriteMsg(conn, firstPacket); errRet != nil {
xl.Warn("sender goroutine for udp work connection closed: %v", errRet)
xl.Warnf("sender goroutine for udp work connection closed: %v", errRet)
return
}
xl.Trace("send udp package to workConn: %s", firstPacket.Content)
xl.Tracef("send udp package to workConn: %s", firstPacket.Content)
}
for {
select {
case udpMsg, ok := <-sv.sendCh:
if !ok {
xl.Info("sender goroutine for udp work connection closed")
xl.Infof("sender goroutine for udp work connection closed")
return
}
if errRet = msg.WriteMsg(conn, udpMsg); errRet != nil {
xl.Warn("sender goroutine for udp work connection closed: %v", errRet)
xl.Warnf("sender goroutine for udp work connection closed: %v", errRet)
return
}
xl.Trace("send udp package to workConn: %s", udpMsg.Content)
xl.Tracef("send udp package to workConn: %s", udpMsg.Content)
case <-closeCh:
return
}
@ -194,7 +194,7 @@ func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
go workConnSenderFn(workConn)
wg.Wait()
xl.Info("sudp worker is closed")
xl.Infof("sudp worker is closed")
}
func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) {
@ -235,7 +235,7 @@ func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) {
if sv.cfg.Transport.UseEncryption {
remote, err = libio.WithEncryption(remote, []byte(sv.cfg.SecretKey))
if err != nil {
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
return nil, err
}
}

@ -79,14 +79,14 @@ func (vm *Manager) keepVisitorsRunning() {
for {
select {
case <-vm.stopCh:
xl.Trace("gracefully shutdown visitor manager")
xl.Tracef("gracefully shutdown visitor manager")
return
case <-ticker.C:
vm.mu.Lock()
for _, cfg := range vm.cfgs {
name := cfg.GetBaseConfig().Name
if _, exist := vm.visitors[name]; !exist {
xl.Info("try to start visitor [%s]", name)
xl.Infof("try to start visitor [%s]", name)
_ = vm.startVisitor(cfg)
}
}
@ -115,10 +115,10 @@ func (vm *Manager) startVisitor(cfg v1.VisitorConfigurer) (err error) {
visitor := NewVisitor(vm.ctx, cfg, vm.clientCfg, vm.helper)
err = visitor.Run()
if err != nil {
xl.Warn("start error: %v", err)
xl.Warnf("start error: %v", err)
} else {
vm.visitors[name] = visitor
xl.Info("start visitor success")
xl.Infof("start visitor success")
}
return
}
@ -156,7 +156,7 @@ func (vm *Manager) UpdateAll(cfgs []v1.VisitorConfigurer) {
}
}
if len(delNames) > 0 {
xl.Info("visitor removed: %v", delNames)
xl.Infof("visitor removed: %v", delNames)
}
addNames := make([]string, 0)
@ -169,7 +169,7 @@ func (vm *Manager) UpdateAll(cfgs []v1.VisitorConfigurer) {
}
}
if len(addNames) > 0 {
xl.Info("visitor added: %v", addNames)
xl.Infof("visitor added: %v", addNames)
}
}

@ -93,7 +93,7 @@ func (sv *XTCPVisitor) worker() {
for {
conn, err := sv.l.Accept()
if err != nil {
xl.Warn("xtcp local listener closed")
xl.Warnf("xtcp local listener closed")
return
}
go sv.handleConn(conn)
@ -105,7 +105,7 @@ func (sv *XTCPVisitor) internalConnWorker() {
for {
conn, err := sv.internalLn.Accept()
if err != nil {
xl.Warn("xtcp internal listener closed")
xl.Warnf("xtcp internal listener closed")
return
}
go sv.handleConn(conn)
@ -140,14 +140,14 @@ func (sv *XTCPVisitor) keepTunnelOpenWorker() {
case <-sv.ctx.Done():
return
case <-ticker.C:
xl.Debug("keepTunnelOpenWorker try to check tunnel...")
xl.Debugf("keepTunnelOpenWorker try to check tunnel...")
conn, err := sv.getTunnelConn()
if err != nil {
xl.Warn("keepTunnelOpenWorker get tunnel connection error: %v", err)
xl.Warnf("keepTunnelOpenWorker get tunnel connection error: %v", err)
_ = sv.retryLimiter.Wait(sv.ctx)
continue
}
xl.Debug("keepTunnelOpenWorker check success")
xl.Debugf("keepTunnelOpenWorker check success")
if conn != nil {
conn.Close()
}
@ -164,7 +164,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
}
}()
xl.Debug("get a new xtcp user connection")
xl.Debugf("get a new xtcp user connection")
// Open a tunnel connection to the server. If there is already a successful hole-punching connection,
// it will be reused. Otherwise, it will block and wait for a successful hole-punching connection until timeout.
@ -176,15 +176,15 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
}
tunnelConn, err := sv.openTunnel(ctx)
if err != nil {
xl.Error("open tunnel error: %v", err)
xl.Errorf("open tunnel error: %v", err)
// no fallback, just return
if sv.cfg.FallbackTo == "" {
return
}
xl.Debug("try to transfer connection to visitor: %s", sv.cfg.FallbackTo)
xl.Debugf("try to transfer connection to visitor: %s", sv.cfg.FallbackTo)
if err := sv.helper.TransferConn(sv.cfg.FallbackTo, userConn); err != nil {
xl.Error("transfer connection to visitor %s error: %v", sv.cfg.FallbackTo, err)
xl.Errorf("transfer connection to visitor %s error: %v", sv.cfg.FallbackTo, err)
return
}
isConnTrasfered = true
@ -195,7 +195,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
if sv.cfg.Transport.UseEncryption {
muxConnRWCloser, err = libio.WithEncryption(muxConnRWCloser, []byte(sv.cfg.SecretKey))
if err != nil {
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
return
}
}
@ -206,9 +206,9 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
}
_, _, errs := libio.Join(userConn, muxConnRWCloser)
xl.Debug("join connections closed")
xl.Debugf("join connections closed")
if len(errs) > 0 {
xl.Trace("join connections errors: %v", errs)
xl.Tracef("join connections errors: %v", errs)
}
}
@ -239,7 +239,7 @@ func (sv *XTCPVisitor) openTunnel(ctx context.Context) (conn net.Conn, err error
if err != nil {
if err != ErrNoTunnelSession {
xl.Warn("get tunnel connection error: %v", err)
xl.Warnf("get tunnel connection error: %v", err)
}
continue
}
@ -268,19 +268,19 @@ func (sv *XTCPVisitor) getTunnelConn() (net.Conn, error) {
// 4. Create a tunnel session using an underlying UDP connection.
func (sv *XTCPVisitor) makeNatHole() {
xl := xlog.FromContextSafe(sv.ctx)
xl.Trace("makeNatHole start")
xl.Tracef("makeNatHole start")
if err := nathole.PreCheck(sv.ctx, sv.helper.MsgTransporter(), sv.cfg.ServerName, 5*time.Second); err != nil {
xl.Warn("nathole precheck error: %v", err)
xl.Warnf("nathole precheck error: %v", err)
return
}
xl.Trace("nathole prepare start")
xl.Tracef("nathole prepare start")
prepareResult, err := nathole.Prepare([]string{sv.clientCfg.NatHoleSTUNServer})
if err != nil {
xl.Warn("nathole prepare error: %v", err)
xl.Warnf("nathole prepare error: %v", err)
return
}
xl.Info("nathole prepare success, nat type: %s, behavior: %s, addresses: %v, assistedAddresses: %v",
xl.Infof("nathole prepare success, nat type: %s, behavior: %s, addresses: %v, assistedAddresses: %v",
prepareResult.NatType, prepareResult.Behavior, prepareResult.Addrs, prepareResult.AssistedAddrs)
listenConn := prepareResult.ListenConn
@ -298,30 +298,30 @@ func (sv *XTCPVisitor) makeNatHole() {
AssistedAddrs: prepareResult.AssistedAddrs,
}
xl.Trace("nathole exchange info start")
xl.Tracef("nathole exchange info start")
natHoleRespMsg, err := nathole.ExchangeInfo(sv.ctx, sv.helper.MsgTransporter(), transactionID, natHoleVisitorMsg, 5*time.Second)
if err != nil {
listenConn.Close()
xl.Warn("nathole exchange info error: %v", err)
xl.Warnf("nathole exchange info error: %v", err)
return
}
xl.Info("get natHoleRespMsg, sid [%s], protocol [%s], candidate address %v, assisted address %v, detectBehavior: %+v",
xl.Infof("get natHoleRespMsg, sid [%s], protocol [%s], candidate address %v, assisted address %v, detectBehavior: %+v",
natHoleRespMsg.Sid, natHoleRespMsg.Protocol, natHoleRespMsg.CandidateAddrs,
natHoleRespMsg.AssistedAddrs, natHoleRespMsg.DetectBehavior)
newListenConn, raddr, err := nathole.MakeHole(sv.ctx, listenConn, natHoleRespMsg, []byte(sv.cfg.SecretKey))
if err != nil {
listenConn.Close()
xl.Warn("make hole error: %v", err)
xl.Warnf("make hole error: %v", err)
return
}
listenConn = newListenConn
xl.Info("establishing nat hole connection successful, sid [%s], remoteAddr [%s]", natHoleRespMsg.Sid, raddr)
xl.Infof("establishing nat hole connection successful, sid [%s], remoteAddr [%s]", natHoleRespMsg.Sid, raddr)
if err := sv.session.Init(listenConn, raddr); err != nil {
listenConn.Close()
xl.Warn("init tunnel session error: %v", err)
xl.Warnf("init tunnel session error: %v", err)
return
}
}

@ -17,8 +17,8 @@ package sub
import (
"fmt"
"os"
"slices"
"github.com/samber/lo"
"github.com/spf13/cobra"
"github.com/fatedier/frp/pkg/config"
@ -55,7 +55,7 @@ func init() {
config.RegisterProxyFlags(cmd, c)
// add sub command for visitor
if lo.Contains(visitorTypes, v1.VisitorType(typ)) {
if slices.Contains(visitorTypes, v1.VisitorType(typ)) {
vc := v1.NewVisitorConfigurerByType(v1.VisitorType(typ))
if vc == nil {
panic("visitor type: " + typ + " not support")

@ -46,7 +46,7 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "./frpc.ini", "config file of frpc")
rootCmd.PersistentFlags().StringVarP(&cfgDir, "config_dir", "", "", "config directory, run one frpc service for each file in config directory")
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc")
rootCmd.PersistentFlags().BoolVarP(&strictConfigMode, "strict_config", "", false, "strict config parsing mode, unknown fields will cause an error")
rootCmd.PersistentFlags().BoolVarP(&strictConfigMode, "strict_config", "", true, "strict config parsing mode, unknown fields will cause an errors")
}
var rootCmd = &cobra.Command{
@ -136,11 +136,11 @@ func startService(
visitorCfgs []v1.VisitorConfigurer,
cfgFile string,
) error {
log.InitLog(cfg.Log.To, cfg.Log.Level, cfg.Log.MaxDays, cfg.Log.DisablePrintColor)
log.InitLogger(cfg.Log.To, cfg.Log.Level, int(cfg.Log.MaxDays), cfg.Log.DisablePrintColor)
if cfgFile != "" {
log.Info("start frpc service for config file [%s]", cfgFile)
defer log.Info("frpc service for config file [%s] stopped", cfgFile)
log.Infof("start frpc service for config file [%s]", cfgFile)
defer log.Infof("frpc service for config file [%s] stopped", cfgFile)
}
svr, err := client.NewService(client.ServiceOptions{
Common: cfg,

@ -40,7 +40,7 @@ var (
func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file of frps")
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frps")
rootCmd.PersistentFlags().BoolVarP(&strictConfigMode, "strict_config", "", false, "strict config parsing mode, unknown fields will cause error")
rootCmd.PersistentFlags().BoolVarP(&strictConfigMode, "strict_config", "", true, "strict config parsing mode, unknown fields will cause errors")
config.RegisterServerConfigFlags(rootCmd, &serverCfg)
}
@ -99,19 +99,19 @@ func Execute() {
}
func runServer(cfg *v1.ServerConfig) (err error) {
log.InitLog(cfg.Log.To, cfg.Log.Level, cfg.Log.MaxDays, cfg.Log.DisablePrintColor)
log.InitLogger(cfg.Log.To, cfg.Log.Level, int(cfg.Log.MaxDays), cfg.Log.DisablePrintColor)
if cfgFile != "" {
log.Info("frps uses config file: %s", cfgFile)
log.Infof("frps uses config file: %s", cfgFile)
} else {
log.Info("frps uses command line arguments for config")
log.Infof("frps uses command line arguments for config")
}
svr, err := server.NewService(cfg)
if err != nil {
return err
}
log.Info("frps started successfully")
log.Infof("frps started successfully")
svr.Run(context.Background())
return
}

@ -164,11 +164,16 @@ healthCheck.type = "tcp"
healthCheck.timeoutSeconds = 3
# If continuous failed in 3 times, the proxy will be removed from frps
healthCheck.maxFailed = 3
# every 10 seconds will do a health check
# Every 10 seconds will do a health check
healthCheck.intervalSeconds = 10
# additional meta info for each proxy
# Additional meta info for each proxy. It will be passed to the server-side plugin for use.
metadatas.var1 = "abc"
metadatas.var2 = "123"
# You can add some extra information to the proxy through annotations.
# These annotations will be displayed on the frps dashboard.
[proxies.annotations]
key1 = "value1"
"prefix/key2" = "value2"
[[proxies]]
name = "ssh_random"

BIN
doc/pic/sponsor_daytona.png Normal file

Binary file not shown.

After

(image error) Size: 56 KiB

@ -1,4 +1,4 @@
FROM golang:1.21 AS building
FROM golang:1.22 AS building
COPY . /building
WORKDIR /building

@ -1,4 +1,4 @@
FROM golang:1.21 AS building
FROM golang:1.22 AS building
COPY . /building
WORKDIR /building

36
go.mod

@ -1,13 +1,11 @@
module github.com/fatedier/frp
go 1.20
go 1.22
require (
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/coreos/go-oidc/v3 v3.6.0
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb
github.com/fatedier/golib v0.1.1-0.20230725122706-dcbaee8eef40
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible
github.com/fatedier/golib v0.4.0
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
@ -15,17 +13,19 @@ require (
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.8
github.com/pelletier/go-toml/v2 v2.1.0
github.com/pion/stun v0.6.1
github.com/pion/stun/v2 v2.0.0
github.com/pires/go-proxyproto v0.7.0
github.com/prometheus/client_golang v1.16.0
github.com/quic-go/quic-go v0.37.7
github.com/quic-go/quic-go v0.41.0
github.com/rodaine/table v1.1.0
github.com/samber/lo v1.38.1
github.com/samber/lo v1.39.0
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
golang.org/x/crypto v0.17.0
golang.org/x/net v0.17.0
github.com/tidwall/gjson v1.17.1
github.com/xtaci/kcp-go/v5 v5.6.7
golang.org/x/crypto v0.18.0
golang.org/x/net v0.19.0
golang.org/x/oauth2 v0.10.0
golang.org/x/sync v0.3.0
golang.org/x/time v0.3.0
@ -42,32 +42,34 @@ require (
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/cpuid/v2 v2.0.6 // indirect
github.com/klauspost/reedsolomon v1.9.15 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/klauspost/reedsolomon v1.12.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/pion/dtls/v2 v2.2.7 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/transport/v2 v2.2.1 // indirect
github.com/pion/transport/v3 v3.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/quic-go/qtls-go1-20 v0.3.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
github.com/templexxx/cpu v0.1.0 // indirect
github.com/templexxx/xorsimd v0.4.2 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
go.uber.org/mock v0.3.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.9.3 // indirect
google.golang.org/appengine v1.6.7 // indirect

92
go.sum

@ -24,12 +24,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
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/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/golib v0.1.1-0.20230725122706-dcbaee8eef40 h1:BVdpWT6viE/mpuRa6txNyRNjtHa1Efrii9Du6/gHfJ0=
github.com/fatedier/golib v0.1.1-0.20230725122706-dcbaee8eef40/go.mod h1:Lmi9U4VfvdRvonSMh1FgXVy1hCXycVyJk4E9ktokknE=
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/golib v0.4.0 h1:lafvYRMhFmqrfIUChKy/f5AXqs1eDSk+GAUtLexN5bU=
github.com/fatedier/golib v0.4.0/go.mod h1:gpu+1vXxtJ072NYaNsn/YWgojDL8Ap2kFZQtbzT2qkg=
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d h1:ynk1ra0RUqDWQfvFi5KtMiSobkVQ3cNc0ODb8CfIETo=
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
@ -40,8 +36,6 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -77,11 +71,12 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
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/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo=
github.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/reedsolomon v1.12.0 h1:I5FEp3xSwVCcEh3F5A7dofEfhXdF/bWhQWPH+XwBFno=
github.com/klauspost/reedsolomon v1.12.0/go.mod h1:EPLZJeh4l27pUGC3aXOjheaoh1I9yut7xTURiW3LQ9Y=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
@ -98,10 +93,12 @@ github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0=
github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ=
github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM=
github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -117,17 +114,15 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/quic-go/qtls-go1-20 v0.3.1 h1:O4BLOM3hwfVF3AcktIylQXyl7Yi2iBNVy5QsV+ySxbg=
github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.37.7 h1:AgKsQLZ1+YCwZd2GYhBUsJDYZwEkA5gENtAjb+MxONU=
github.com/quic-go/quic-go v0.37.7/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@ -141,35 +136,44 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/templexxx/cpu v0.1.0 h1:wVM+WIJP2nYaxVxqgHPD4wGA2aJ9rvrQRV8CvFzNb40=
github.com/templexxx/cpu v0.1.0/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
github.com/templexxx/xorsimd v0.4.2 h1:ocZZ+Nvu65LGHmCLZ7OoCtg8Fx8jnHKK37SjvngUoVI=
github.com/templexxx/xorsimd v0.4.2/go.mod h1:HgwaPoDREdi6OnULpSfxhzaiiSUY4Fi3JPn1wpt28NI=
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
github.com/xtaci/kcp-go/v5 v5.6.7 h1:7+rnxNFIsjEwTXQk4cSZpXM4pO0hqtpwE1UFFoJBffA=
github.com/xtaci/kcp-go/v5 v5.6.7/go.mod h1:oE9j2NVqAkuKO5o8ByKGch3vgVX3BNf8zqP8JiGq0bM=
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/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-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -179,12 +183,13 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
@ -192,7 +197,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
@ -203,26 +207,30 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
@ -233,15 +241,12 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
@ -264,6 +269,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

@ -17,9 +17,9 @@ package auth
import (
"context"
"fmt"
"slices"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/samber/lo"
"golang.org/x/oauth2/clientcredentials"
v1 "github.com/fatedier/frp/pkg/config/v1"
@ -70,7 +70,7 @@ func (auth *OidcAuthProvider) SetLogin(loginMsg *msg.Login) (err error) {
}
func (auth *OidcAuthProvider) SetPing(pingMsg *msg.Ping) (err error) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
return nil
}
@ -79,7 +79,7 @@ func (auth *OidcAuthProvider) SetPing(pingMsg *msg.Ping) (err error) {
}
func (auth *OidcAuthProvider) SetNewWorkConn(newWorkConnMsg *msg.NewWorkConn) (err error) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
return nil
}
@ -135,7 +135,7 @@ func (auth *OidcAuthConsumer) verifyPostLoginToken(privilegeKey string) (err err
}
func (auth *OidcAuthConsumer) VerifyPing(pingMsg *msg.Ping) (err error) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
return nil
}
@ -143,7 +143,7 @@ func (auth *OidcAuthConsumer) VerifyPing(pingMsg *msg.Ping) (err error) {
}
func (auth *OidcAuthConsumer) VerifyNewWorkConn(newWorkConnMsg *msg.NewWorkConn) (err error) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
return nil
}

@ -16,10 +16,9 @@ package auth
import (
"fmt"
"slices"
"time"
"github.com/samber/lo"
v1 "github.com/fatedier/frp/pkg/config/v1"
"github.com/fatedier/frp/pkg/msg"
"github.com/fatedier/frp/pkg/util/util"
@ -43,7 +42,7 @@ func (auth *TokenAuthSetterVerifier) SetLogin(loginMsg *msg.Login) error {
}
func (auth *TokenAuthSetterVerifier) SetPing(pingMsg *msg.Ping) error {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
return nil
}
@ -53,7 +52,7 @@ func (auth *TokenAuthSetterVerifier) SetPing(pingMsg *msg.Ping) error {
}
func (auth *TokenAuthSetterVerifier) SetNewWorkConn(newWorkConnMsg *msg.NewWorkConn) error {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
return nil
}
@ -70,7 +69,7 @@ func (auth *TokenAuthSetterVerifier) VerifyLogin(m *msg.Login) error {
}
func (auth *TokenAuthSetterVerifier) VerifyPing(m *msg.Ping) error {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
return nil
}
@ -81,7 +80,7 @@ func (auth *TokenAuthSetterVerifier) VerifyPing(m *msg.Ping) error {
}
func (auth *TokenAuthSetterVerifier) VerifyNewWorkConn(m *msg.NewWorkConn) error {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
return nil
}

@ -18,9 +18,9 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"github.com/samber/lo"
"gopkg.in/ini.v1"
legacyauth "github.com/fatedier/frp/pkg/auth/legacy"
@ -399,7 +399,7 @@ func (cfg *ClientCommonConf) Validate() error {
}
}
if !lo.Contains([]string{"tcp", "kcp", "quic", "websocket", "wss"}, cfg.Protocol) {
if !slices.Contains([]string{"tcp", "kcp", "quic", "websocket", "wss"}, cfg.Protocol) {
return fmt.Errorf("invalid protocol")
}

@ -175,6 +175,9 @@ func transformHeadersFromPluginParams(params map[string]string) v1.HeaderOperati
continue
}
if k = strings.TrimPrefix(k, "plugin_header_"); k != "" {
if out.Set == nil {
out.Set = make(map[string]string)
}
out.Set[k] = v
}
}

@ -45,15 +45,6 @@ func NewBandwidthQuantity(s string) (BandwidthQuantity, error) {
return q, nil
}
func MustBandwidthQuantity(s string) BandwidthQuantity {
q := BandwidthQuantity{}
err := q.UnmarshalString(s)
if err != nil {
panic(err)
}
return q
}
func (q *BandwidthQuantity) Equal(u *BandwidthQuantity) bool {
if q == nil && u == nil {
return true

@ -57,7 +57,7 @@ func (c *TypedClientPluginOptions) UnmarshalJSON(b []byte) error {
}
if err := decoder.Decode(options); err != nil {
return err
return fmt.Errorf("unmarshal ClientPluginOptions error: %v", err)
}
c.ClientPluginOptions = options
return nil

@ -105,9 +105,10 @@ type DomainConfig struct {
}
type ProxyBaseConfig struct {
Name string `json:"name"`
Type string `json:"type"`
Transport ProxyTransport `json:"transport,omitempty"`
Name string `json:"name"`
Type string `json:"type"`
Annotations map[string]string `json:"annotations,omitempty"`
Transport ProxyTransport `json:"transport,omitempty"`
// metadata info for each proxy
Metadatas map[string]string `json:"metadatas,omitempty"`
LoadBalancer LoadBalancerConfig `json:"loadBalancer,omitempty"`
@ -138,6 +139,7 @@ func (c *ProxyBaseConfig) MarshalToMsg(m *msg.NewProxy) {
m.Group = c.LoadBalancer.Group
m.GroupKey = c.LoadBalancer.GroupKey
m.Metas = c.Metadatas
m.Annotations = c.Annotations
}
func (c *ProxyBaseConfig) UnmarshalFromMsg(m *msg.NewProxy) {
@ -154,6 +156,7 @@ func (c *ProxyBaseConfig) UnmarshalFromMsg(m *msg.NewProxy) {
c.LoadBalancer.Group = m.Group
c.LoadBalancer.GroupKey = m.GroupKey
c.Metadatas = m.Metas
c.Annotations = m.Annotations
}
type TypedProxyConfig struct {
@ -183,7 +186,7 @@ func (c *TypedProxyConfig) UnmarshalJSON(b []byte) error {
decoder.DisallowUnknownFields()
}
if err := decoder.Decode(configurer); err != nil {
return err
return fmt.Errorf("unmarshal ProxyConfig error: %v", err)
}
c.ProxyConfigurer = configurer
return nil

@ -18,6 +18,7 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"github.com/samber/lo"
@ -29,7 +30,7 @@ func ValidateClientCommonConfig(c *v1.ClientCommonConfig) (Warning, error) {
warnings Warning
errs error
)
if !lo.Contains(SupportedAuthMethods, c.Auth.Method) {
if !slices.Contains(SupportedAuthMethods, c.Auth.Method) {
errs = AppendError(errs, fmt.Errorf("invalid auth method, optional values are %v", SupportedAuthMethods))
}
if !lo.Every(SupportedAuthAdditionalScopes, c.Auth.AdditionalScopes) {
@ -63,7 +64,7 @@ func ValidateClientCommonConfig(c *v1.ClientCommonConfig) (Warning, error) {
warnings = AppendError(warnings, checkTLSConfig("transport.tls.trustedCaFile", c.Transport.TLS.TrustedCaFile))
}
if !lo.Contains(SupportedTransportProtocols, c.Transport.Protocol) {
if !slices.Contains(SupportedTransportProtocols, c.Transport.Protocol) {
errs = AppendError(errs, fmt.Errorf("invalid transport.protocol, optional values are %v", SupportedTransportProtocols))
}

@ -16,8 +16,7 @@ package validation
import (
"fmt"
"github.com/samber/lo"
"slices"
v1 "github.com/fatedier/frp/pkg/config/v1"
)
@ -44,7 +43,7 @@ func ValidatePort(port int, fieldPath string) error {
}
func validateLogConfig(c *v1.LogConfig) error {
if !lo.Contains(SupportedLogLevels, c.Level) {
if !slices.Contains(SupportedLogLevels, c.Level) {
return fmt.Errorf("invalid log level, optional values are %v", SupportedLogLevels)
}
return nil

@ -17,9 +17,10 @@ package validation
import (
"errors"
"fmt"
"slices"
"strings"
"github.com/samber/lo"
"k8s.io/apimachinery/pkg/util/validation"
v1 "github.com/fatedier/frp/pkg/config/v1"
)
@ -29,11 +30,13 @@ func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {
return errors.New("name should not be empty")
}
if !lo.Contains([]string{"", "v1", "v2"}, c.Transport.ProxyProtocolVersion) {
if err := ValidateAnnotations(c.Annotations); err != nil {
return err
}
if !slices.Contains([]string{"", "v1", "v2"}, c.Transport.ProxyProtocolVersion) {
return fmt.Errorf("not support proxy protocol version: %s", c.Transport.ProxyProtocolVersion)
}
if !lo.Contains([]string{"client", "server"}, c.Transport.BandwidthLimitMode) {
if !slices.Contains([]string{"client", "server"}, c.Transport.BandwidthLimitMode) {
return fmt.Errorf("bandwidth limit mode should be client or server")
}
@ -43,7 +46,7 @@ func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {
}
}
if !lo.Contains([]string{"", "tcp", "http"}, c.HealthCheck.Type) {
if !slices.Contains([]string{"", "tcp", "http"}, c.HealthCheck.Type) {
return fmt.Errorf("not support health check type: %s", c.HealthCheck.Type)
}
if c.HealthCheck.Type != "" {
@ -61,7 +64,10 @@ func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {
return nil
}
func validateProxyBaseConfigForServer(c *v1.ProxyBaseConfig, s *v1.ServerConfig) error {
func validateProxyBaseConfigForServer(c *v1.ProxyBaseConfig) error {
if err := ValidateAnnotations(c.Annotations); err != nil {
return err
}
return nil
}
@ -133,7 +139,7 @@ func validateTCPMuxProxyConfigForClient(c *v1.TCPMuxProxyConfig) error {
return err
}
if !lo.Contains([]string{string(v1.TCPMultiplexerHTTPConnect)}, c.Multiplexer) {
if !slices.Contains([]string{string(v1.TCPMultiplexerHTTPConnect)}, c.Multiplexer) {
return fmt.Errorf("not support multiplexer: %s", c.Multiplexer)
}
return nil
@ -161,7 +167,7 @@ func validateSUDPProxyConfigForClient(c *v1.SUDPProxyConfig) error {
func ValidateProxyConfigurerForServer(c v1.ProxyConfigurer, s *v1.ServerConfig) error {
base := c.GetBaseConfig()
if err := validateProxyBaseConfigForServer(base, s); err != nil {
if err := validateProxyBaseConfigForServer(base); err != nil {
return err
}
@ -231,3 +237,34 @@ func validateXTCPProxyConfigForServer(c *v1.XTCPProxyConfig, s *v1.ServerConfig)
func validateSUDPProxyConfigForServer(c *v1.SUDPProxyConfig, s *v1.ServerConfig) error {
return nil
}
// ValidateAnnotations validates that a set of annotations are correctly defined.
func ValidateAnnotations(annotations map[string]string) error {
if len(annotations) == 0 {
return nil
}
var errs error
for k := range annotations {
for _, msg := range validation.IsQualifiedName(strings.ToLower(k)) {
errs = AppendError(errs, fmt.Errorf("annotation key %s is invalid: %s", k, msg))
}
}
if err := ValidateAnnotationsSize(annotations); err != nil {
errs = AppendError(errs, err)
}
return errs
}
const TotalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB
func ValidateAnnotationsSize(annotations map[string]string) error {
var totalSize int64
for k, v := range annotations {
totalSize += (int64)(len(k)) + (int64)(len(v))
}
if totalSize > (int64)(TotalAnnotationSizeLimitB) {
return fmt.Errorf("annotations size %d is larger than limit %d", totalSize, TotalAnnotationSizeLimitB)
}
return nil
}

@ -16,6 +16,7 @@ package validation
import (
"fmt"
"slices"
"github.com/samber/lo"
@ -27,7 +28,7 @@ func ValidateServerConfig(c *v1.ServerConfig) (Warning, error) {
warnings Warning
errs error
)
if !lo.Contains(SupportedAuthMethods, c.Auth.Method) {
if !slices.Contains(SupportedAuthMethods, c.Auth.Method) {
errs = AppendError(errs, fmt.Errorf("invalid auth method, optional values are %v", SupportedAuthMethods))
}
if !lo.Every(SupportedAuthAdditionalScopes, c.Auth.AdditionalScopes) {

@ -17,8 +17,7 @@ package validation
import (
"errors"
"fmt"
"github.com/samber/lo"
"slices"
v1 "github.com/fatedier/frp/pkg/config/v1"
)
@ -56,7 +55,7 @@ func validateVisitorBaseConfig(c *v1.VisitorBaseConfig) error {
}
func validateXTCPVisitorConfig(c *v1.XTCPVisitorConfig) error {
if !lo.Contains([]string{"kcp", "quic"}, c.Protocol) {
if !slices.Contains([]string{"kcp", "quic"}, c.Protocol) {
return fmt.Errorf("protocol should be kcp or quic")
}
return nil

@ -114,7 +114,7 @@ func (c *TypedVisitorConfig) UnmarshalJSON(b []byte) error {
decoder.DisallowUnknownFields()
}
if err := decoder.Decode(configurer); err != nil {
return err
return fmt.Errorf("unmarshal VisitorConfig error: %v", err)
}
c.VisitorConfigurer = configurer
return nil

@ -62,7 +62,7 @@ func (m *serverMetrics) run() {
time.Sleep(12 * time.Hour)
start := time.Now()
count, total := m.clearUselessInfo(time.Duration(7*24) * time.Hour)
log.Debug("clear useless proxy statistics data count %d/%d, cost %v", count, total, time.Since(start))
log.Debugf("clear useless proxy statistics data count %d/%d, cost %v", count, total, time.Since(start))
}
}()
}
@ -80,7 +80,7 @@ func (m *serverMetrics) clearUselessInfo(continuousOfflineDuration time.Duration
time.Since(data.LastCloseTime) > continuousOfflineDuration {
delete(m.info.ProxyStatistics, name)
count++
log.Trace("clear proxy [%s]'s statistics data, lastCloseTime: [%s]", name, data.LastCloseTime.String())
log.Tracef("clear proxy [%s]'s statistics data, lastCloseTime: [%s]", name, data.LastCloseTime.String())
}
}
return count, total

@ -42,7 +42,3 @@ func ReadMsgInto(c io.Reader, msg Message) (err error) {
func WriteMsg(c io.Writer, msg interface{}) (err error) {
return msgCtl.WriteMsg(c, msg)
}
func Pack(msg interface{}) (data []byte, err error) {
return msgCtl.Pack(msg)
}

@ -108,6 +108,7 @@ type NewProxy struct {
Group string `json:"group,omitempty"`
GroupKey string `json:"group_key,omitempty"`
Metas map[string]string `json:"metas,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
// tcp and udp only
RemotePort int `json:"remote_port,omitempty"`

@ -15,6 +15,8 @@
package nathole
import (
"cmp"
"slices"
"sync"
"time"
@ -224,7 +226,7 @@ func (mhr *MakeHoleRecords) ReportSuccess(mode int, index int) {
}
score.Score += 2
score.Score = lo.Min([]int{score.Score, 10})
score.Score = min(score.Score, 10)
return
}
}
@ -233,12 +235,12 @@ func (mhr *MakeHoleRecords) Recommand() (mode, index int) {
mhr.mu.Lock()
defer mhr.mu.Unlock()
maxScore := lo.MaxBy(mhr.scores, func(item, max *BehaviorScore) bool {
return item.Score > max.Score
})
if maxScore == nil {
if len(mhr.scores) == 0 {
return 0, 0
}
maxScore := slices.MaxFunc(mhr.scores, func(a, b *BehaviorScore) int {
return cmp.Compare(a.Score, b.Score)
})
maxScore.Score--
mhr.LastUpdateTime = time.Now()
return maxScore.Mode, maxScore.Index

@ -17,9 +17,8 @@ package nathole
import (
"fmt"
"net"
"slices"
"strconv"
"github.com/samber/lo"
)
const (
@ -59,7 +58,7 @@ func ClassifyNATFeature(addresses []string, localIPs []string) (*NatFeature, err
if err != nil {
return nil, err
}
if lo.Contains(localIPs, ip) {
if slices.Contains(localIPs, ip) {
natFeature.PublicNetwork = true
}

@ -20,6 +20,7 @@ import (
"encoding/hex"
"fmt"
"net"
"slices"
"strconv"
"sync"
"time"
@ -72,7 +73,7 @@ type Session struct {
func (s *Session) genAnalysisKey() {
hash := md5.New()
vIPs := lo.Uniq(parseIPs(s.visitorMsg.MappedAddrs))
vIPs := slices.Compact(parseIPs(s.visitorMsg.MappedAddrs))
if len(vIPs) > 0 {
hash.Write([]byte(vIPs[0]))
}
@ -80,7 +81,7 @@ func (s *Session) genAnalysisKey() {
hash.Write([]byte(s.vNatFeature.Behavior))
hash.Write([]byte(strconv.FormatBool(s.vNatFeature.RegularPortsChange)))
cIPs := lo.Uniq(parseIPs(s.clientMsg.MappedAddrs))
cIPs := slices.Compact(parseIPs(s.clientMsg.MappedAddrs))
if len(cIPs) > 0 {
hash.Write([]byte(cIPs[0]))
}
@ -114,7 +115,7 @@ func (c *Controller) CleanWorker(ctx context.Context) {
case <-ticker.C:
start := time.Now()
count, total := c.analyzer.Clean()
log.Trace("clean %d/%d nathole analysis data, cost %v", count, total, time.Since(start))
log.Tracef("clean %d/%d nathole analysis data, cost %v", count, total, time.Since(start))
case <-ctx.Done():
return
}
@ -156,7 +157,7 @@ func (c *Controller) HandleVisitor(m *msg.NatHoleVisitor, transporter transport.
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)))
return
}
if !lo.Contains(cfg.allowUsers, visitorUser) && !lo.Contains(cfg.allowUsers, "*") {
if !slices.Contains(cfg.allowUsers, visitorUser) && !slices.Contains(cfg.allowUsers, "*") {
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, fmt.Sprintf("xtcp visitor user [%s] not allowed for [%s]", visitorUser, m.ProxyName)))
return
}
@ -190,11 +191,11 @@ func (c *Controller) HandleVisitor(m *msg.NatHoleVisitor, transporter transport.
return nil
}()
if err != nil {
log.Warn("handle visitorMsg error: %v", err)
log.Warnf("handle visitorMsg error: %v", err)
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, err.Error()))
return
}
log.Trace("handle visitor message, sid [%s], server name: %s", sid, m.ProxyName)
log.Tracef("handle visitor message, sid [%s], server name: %s", sid, m.ProxyName)
defer func() {
c.mu.Lock()
@ -212,14 +213,14 @@ func (c *Controller) HandleVisitor(m *msg.NatHoleVisitor, transporter transport.
select {
case <-session.notifyCh:
case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
log.Debug("wait for NatHoleClient message timeout, sid [%s]", sid)
log.Debugf("wait for NatHoleClient message timeout, sid [%s]", sid)
return
}
// Make hole-punching decisions based on the NAT information of the client and visitor.
vResp, cResp, err := c.analysis(session)
if err != nil {
log.Debug("sid [%s] analysis error: %v", err)
log.Debugf("sid [%s] analysis error: %v", err)
vResp = c.GenNatHoleResponse(session.visitorMsg.TransactionID, nil, err.Error())
cResp = c.GenNatHoleResponse(session.clientMsg.TransactionID, nil, err.Error())
}
@ -256,7 +257,7 @@ func (c *Controller) HandleClient(m *msg.NatHoleClient, transporter transport.Me
if !ok {
return
}
log.Trace("handle client message, sid [%s], server name: %s", session.sid, m.ProxyName)
log.Tracef("handle client message, sid [%s], server name: %s", session.sid, m.ProxyName)
session.clientMsg = m
session.clientTransporter = transporter
select {
@ -270,13 +271,13 @@ func (c *Controller) HandleReport(m *msg.NatHoleReport) {
session, ok := c.sessions[m.Sid]
c.mu.RUnlock()
if !ok {
log.Trace("sid [%s] report make hole success: %v, but session not found", m.Sid, m.Success)
log.Tracef("sid [%s] report make hole success: %v, but session not found", m.Sid, m.Success)
return
}
if m.Success {
c.analyzer.ReportSuccess(session.analysisKey, session.recommandMode, session.recommandIndex)
}
log.Info("sid [%s] report make hole success: %v, mode %v, index %v",
log.Infof("sid [%s] report make hole success: %v, mode %v, index %v",
m.Sid, m.Success, session.recommandMode, session.recommandIndex)
}
@ -317,7 +318,7 @@ func (c *Controller) analysis(session *Session) (*msg.NatHoleResp, *msg.NatHoleR
session.cBehavior = cBehavior
session.vBehavior = vBehavior
timeoutMs := lo.Max([]int{cBehavior.SendDelayMs, vBehavior.SendDelayMs}) + 5000
timeoutMs := max(cBehavior.SendDelayMs, vBehavior.SendDelayMs) + 5000
if cBehavior.ListenRandomPorts > 0 || vBehavior.ListenRandomPorts > 0 {
timeoutMs += 30000
}
@ -327,8 +328,8 @@ func (c *Controller) analysis(session *Session) (*msg.NatHoleResp, *msg.NatHoleR
TransactionID: vm.TransactionID,
Sid: session.sid,
Protocol: protocol,
CandidateAddrs: lo.Uniq(cm.MappedAddrs),
AssistedAddrs: lo.Uniq(cm.AssistedAddrs),
CandidateAddrs: slices.Compact(cm.MappedAddrs),
AssistedAddrs: slices.Compact(cm.AssistedAddrs),
DetectBehavior: msg.NatHoleDetectBehavior{
Mode: mode,
Role: vBehavior.Role,
@ -344,8 +345,8 @@ func (c *Controller) analysis(session *Session) (*msg.NatHoleResp, *msg.NatHoleR
TransactionID: cm.TransactionID,
Sid: session.sid,
Protocol: protocol,
CandidateAddrs: lo.Uniq(vm.MappedAddrs),
AssistedAddrs: lo.Uniq(vm.AssistedAddrs),
CandidateAddrs: slices.Compact(vm.MappedAddrs),
AssistedAddrs: slices.Compact(vm.AssistedAddrs),
DetectBehavior: msg.NatHoleDetectBehavior{
Mode: mode,
Role: cBehavior.Role,
@ -358,10 +359,10 @@ func (c *Controller) analysis(session *Session) (*msg.NatHoleResp, *msg.NatHoleR
},
}
log.Debug("sid [%s] visitor nat: %+v, candidateAddrs: %v; client nat: %+v, candidateAddrs: %v, protocol: %s",
log.Debugf("sid [%s] visitor nat: %+v, candidateAddrs: %v; client nat: %+v, candidateAddrs: %v, protocol: %s",
session.sid, *vNatFeature, vm.MappedAddrs, *cNatFeature, cm.MappedAddrs, protocol)
log.Debug("sid [%s] visitor detect behavior: %+v", session.sid, vResp.DetectBehavior)
log.Debug("sid [%s] client detect behavior: %+v", session.sid, cResp.DetectBehavior)
log.Debugf("sid [%s] visitor detect behavior: %+v", session.sid, vResp.DetectBehavior)
log.Debugf("sid [%s] client detect behavior: %+v", session.sid, cResp.DetectBehavior)
return vResp, cResp, nil
}
@ -384,8 +385,8 @@ func getRangePorts(addrs []string, difference, maxNumber int) []msg.PortsRange {
return nil
}
ports = append(ports, msg.PortsRange{
From: lo.Max([]int{port - difference - 5, port - maxNumber, 1}),
To: lo.Min([]int{port + difference + 5, port + maxNumber, 65535}),
From: max(port-difference-5, port-maxNumber, 1),
To: min(port+difference+5, port+maxNumber, 65535),
})
return ports
}

@ -19,7 +19,7 @@ import (
"net"
"time"
"github.com/pion/stun"
"github.com/pion/stun/v2"
)
var responseTimeout = 3 * time.Second

@ -19,12 +19,12 @@ import (
"fmt"
"math/rand"
"net"
"slices"
"strconv"
"strings"
"time"
"github.com/fatedier/golib/pool"
"github.com/samber/lo"
"golang.org/x/net/ipv4"
"k8s.io/apimachinery/pkg/util/sets"
@ -204,7 +204,7 @@ func MakeHole(ctx context.Context, listenConn *net.UDPConn, m *msg.NatHoleResp,
for i := 0; i < m.DetectBehavior.ListenRandomPorts; i++ {
tmpConn, err := net.ListenUDP("udp4", nil)
if err != nil {
xl.Warn("listen random udp addr error: %v", err)
xl.Warnf("listen random udp addr error: %v", err)
continue
}
listenConns = append(listenConns, tmpConn)
@ -212,11 +212,11 @@ func MakeHole(ctx context.Context, listenConn *net.UDPConn, m *msg.NatHoleResp,
}
}
detectAddrs = lo.Uniq(detectAddrs)
detectAddrs = slices.Compact(detectAddrs)
for _, detectAddr := range detectAddrs {
for _, conn := range listenConns {
if err := sendSidMessage(ctx, conn, m.Sid, transactionID, detectAddr, key, m.DetectBehavior.TTL); err != nil {
xl.Trace("send sid message from %s to %s error: %v", conn.LocalAddr(), detectAddr, err)
xl.Tracef("send sid message from %s to %s error: %v", conn.LocalAddr(), detectAddr, err)
}
}
}
@ -289,16 +289,16 @@ func waitDetectMessage(
if err != nil {
return nil, err
}
xl.Debug("get udp message local %s, from %s", conn.LocalAddr(), raddr)
xl.Debugf("get udp message local %s, from %s", conn.LocalAddr(), raddr)
var m msg.NatHoleSid
if err := DecodeMessageInto(buf[:n], key, &m); err != nil {
xl.Warn("decode sid message error: %v", err)
xl.Warnf("decode sid message error: %v", err)
continue
}
pool.PutBuf(buf)
if m.Sid != sid {
xl.Warn("get sid message with wrong sid: %s, expect: %s", m.Sid, sid)
xl.Warnf("get sid message with wrong sid: %s, expect: %s", m.Sid, sid)
continue
}
@ -311,7 +311,7 @@ func waitDetectMessage(
m.Response = true
buf2, err := EncodeMessage(&m, key)
if err != nil {
xl.Warn("encode sid message error: %v", err)
xl.Warnf("encode sid message error: %v", err)
continue
}
_, _ = conn.WriteToUDP(buf2, raddr)
@ -329,7 +329,7 @@ func sendSidMessage(
if ttl > 0 {
ttlStr = fmt.Sprintf(" with ttl %d", ttl)
}
xl.Trace("send sid message from %s to %s%s", conn.LocalAddr(), addr, ttlStr)
xl.Tracef("send sid message from %s to %s%s", conn.LocalAddr(), addr, ttlStr)
raddr, err := net.ResolveUDPAddr("udp4", addr)
if err != nil {
return err
@ -351,14 +351,14 @@ func sendSidMessage(
uConn := ipv4.NewConn(conn)
original, err := uConn.TTL()
if err != nil {
xl.Trace("get ttl error %v", err)
xl.Tracef("get ttl error %v", err)
return err
}
xl.Trace("original ttl %d", original)
xl.Tracef("original ttl %d", original)
err = uConn.SetTTL(ttl)
if err != nil {
xl.Trace("set ttl error %v", err)
xl.Tracef("set ttl error %v", err)
} else {
defer func() {
_ = uConn.SetTTL(original)
@ -377,12 +377,12 @@ func sendSidMessageToRangePorts(
sendFunc func(*net.UDPConn, string) error,
) {
xl := xlog.FromContextSafe(ctx)
for _, ip := range lo.Uniq(parseIPs(addrs)) {
for _, ip := range slices.Compact(parseIPs(addrs)) {
for _, portsRange := range ports {
for i := portsRange.From; i <= portsRange.To; i++ {
detectAddr := net.JoinHostPort(ip, strconv.Itoa(i))
if err := sendFunc(conn, detectAddr); err != nil {
xl.Trace("send sid message from %s to %s error: %v", conn.LocalAddr(), detectAddr, err)
xl.Tracef("send sid message from %s to %s error: %v", conn.LocalAddr(), detectAddr, err)
}
time.Sleep(2 * time.Millisecond)
}
@ -419,10 +419,10 @@ func sendSidMessageToRandomPorts(
continue
}
for _, ip := range lo.Uniq(parseIPs(addrs)) {
for _, ip := range slices.Compact(parseIPs(addrs)) {
detectAddr := net.JoinHostPort(ip, strconv.Itoa(port))
if err := sendFunc(conn, detectAddr); err != nil {
xl.Trace("send sid message from %s to %s error: %v", conn.LocalAddr(), detectAddr, err)
xl.Tracef("send sid message from %s to %s error: %v", conn.LocalAddr(), detectAddr, err)
}
time.Sleep(time.Millisecond * 15)
}

@ -21,7 +21,7 @@ import (
"strconv"
"github.com/fatedier/golib/crypto"
"github.com/pion/stun"
"github.com/pion/stun/v2"
"github.com/fatedier/frp/pkg/msg"
)

@ -53,7 +53,8 @@ func NewHTTP2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
}
rp := &httputil.ReverseProxy{
Director: func(req *http.Request) {
Rewrite: func(r *httputil.ProxyRequest) {
req := r.Out
req.URL.Scheme = "https"
req.URL.Host = p.opts.LocalAddr
if p.opts.HostHeaderRewrite != "" {

@ -50,7 +50,8 @@ func NewHTTPS2HTTPPlugin(options v1.ClientPluginOptions) (Plugin, error) {
}
rp := &httputil.ReverseProxy{
Director: func(req *http.Request) {
Rewrite: func(r *httputil.ProxyRequest) {
req := r.Out
req.URL.Scheme = "http"
req.URL.Host = p.opts.LocalAddr
if p.opts.HostHeaderRewrite != "" {

@ -55,7 +55,8 @@ func NewHTTPS2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
}
rp := &httputil.ReverseProxy{
Director: func(req *http.Request) {
Rewrite: func(r *httputil.ProxyRequest) {
req := r.Out
req.URL.Scheme = "https"
req.URL.Host = p.opts.LocalAddr
if p.opts.HostHeaderRewrite != "" {

@ -86,7 +86,7 @@ func (m *Manager) Login(content *LoginContent) (*LoginContent, error) {
for _, p := range m.loginPlugins {
res, retContent, err = p.Handle(ctx, OpLogin, *content)
if err != nil {
xl.Warn("send Login request to plugin [%s] error: %v", p.Name(), err)
xl.Warnf("send Login request to plugin [%s] error: %v", p.Name(), err)
return nil, errors.New("send Login request to plugin error")
}
if res.Reject {
@ -120,7 +120,7 @@ func (m *Manager) NewProxy(content *NewProxyContent) (*NewProxyContent, error) {
for _, p := range m.newProxyPlugins {
res, retContent, err = p.Handle(ctx, OpNewProxy, *content)
if err != nil {
xl.Warn("send NewProxy request to plugin [%s] error: %v", p.Name(), err)
xl.Warnf("send NewProxy request to plugin [%s] error: %v", p.Name(), err)
return nil, errors.New("send NewProxy request to plugin error")
}
if res.Reject {
@ -147,7 +147,7 @@ func (m *Manager) CloseProxy(content *CloseProxyContent) error {
for _, p := range m.closeProxyPlugins {
_, _, err := p.Handle(ctx, OpCloseProxy, *content)
if err != nil {
xl.Warn("send CloseProxy request to plugin [%s] error: %v", p.Name(), err)
xl.Warnf("send CloseProxy request to plugin [%s] error: %v", p.Name(), err)
errs = append(errs, fmt.Sprintf("[%s]: %v", p.Name(), err))
}
}
@ -179,7 +179,7 @@ func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
for _, p := range m.pingPlugins {
res, retContent, err = p.Handle(ctx, OpPing, *content)
if err != nil {
xl.Warn("send Ping request to plugin [%s] error: %v", p.Name(), err)
xl.Warnf("send Ping request to plugin [%s] error: %v", p.Name(), err)
return nil, errors.New("send Ping request to plugin error")
}
if res.Reject {
@ -213,7 +213,7 @@ func (m *Manager) NewWorkConn(content *NewWorkConnContent) (*NewWorkConnContent,
for _, p := range m.newWorkConnPlugins {
res, retContent, err = p.Handle(ctx, OpNewWorkConn, *content)
if err != nil {
xl.Warn("send NewWorkConn request to plugin [%s] error: %v", p.Name(), err)
xl.Warnf("send NewWorkConn request to plugin [%s] error: %v", p.Name(), err)
return nil, errors.New("send NewWorkConn request to plugin error")
}
if res.Reject {
@ -247,7 +247,7 @@ func (m *Manager) NewUserConn(content *NewUserConnContent) (*NewUserConnContent,
for _, p := range m.newUserConnPlugins {
res, retContent, err = p.Handle(ctx, OpNewUserConn, *content)
if err != nil {
xl.Info("send NewUserConn request to plugin [%s] error: %v", p.Name(), err)
xl.Infof("send NewUserConn request to plugin [%s] error: %v", p.Name(), err)
return nil, errors.New("send NewUserConn request to plugin error")
}
if res.Reject {

@ -75,7 +75,7 @@ func NewGateway(
sshConfig.PublicKeyCallback = func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
authorizedKeysMap, err := loadAuthorizedKeysFromFile(cfg.AuthorizedKeysFile)
if err != nil {
log.Error("load authorized keys file error: %v", err)
log.Errorf("load authorized keys file error: %v", err)
return nil, fmt.Errorf("internal error")
}
@ -120,7 +120,7 @@ func (g *Gateway) handleConn(conn net.Conn) {
return
}
if err := ts.Run(); err != nil {
log.Error("ssh tunnel server run error: %v", err)
log.Errorf("ssh tunnel server run error: %v", err)
}
}

@ -20,12 +20,12 @@ import (
"errors"
"fmt"
"net"
"slices"
"strings"
"sync"
"time"
libio "github.com/fatedier/golib/io"
"github.com/samber/lo"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"golang.org/x/crypto/ssh"
@ -123,7 +123,7 @@ func (s *TunnelServer) Run() error {
// join workConn and ssh channel
c, err := s.openConn(addr)
if err != nil {
log.Trace("open conn error: %v", err)
log.Tracef("open conn error: %v", err)
workConn.Close()
return false
}
@ -167,7 +167,7 @@ func (s *TunnelServer) Run() error {
if ps, err := s.waitProxyStatusReady(pc.GetBaseConfig().Name, time.Second); err != nil {
s.writeToClient(err.Error())
log.Warn("wait proxy status ready error: %v", err)
log.Warnf("wait proxy status ready error: %v", err)
} else {
// success
s.writeToClient(createSuccessInfo(clientCfg.User, pc, ps))
@ -175,7 +175,7 @@ func (s *TunnelServer) Run() error {
}
s.vc.Close()
log.Trace("ssh tunnel connection from %v closed", sshConn.RemoteAddr())
log.Tracef("ssh tunnel connection from %v closed", sshConn.RemoteAddr())
s.closeDoneChOnce.Do(func() {
_ = sshConn.Close()
close(s.doneCh)
@ -262,7 +262,7 @@ func (s *TunnelServer) parseClientAndProxyConfigurer(_ *tcpipForward, extraPaylo
}
proxyType := strings.TrimSpace(args[0])
supportTypes := []string{"tcp", "http", "https", "tcpmux", "stcp"}
if !lo.Contains(supportTypes, proxyType) {
if !slices.Contains(supportTypes, proxyType) {
return nil, nil, helpMessage, fmt.Errorf("invalid proxy type: %s, support types: %v", proxyType, supportTypes)
}
pc := v1.NewProxyConfigurerByType(v1.ProxyType(proxyType))

@ -15,78 +15,65 @@
package log
import (
"fmt"
"os"
"github.com/fatedier/beego/logs"
"github.com/fatedier/golib/log"
)
// Log is the under log object
var Log *logs.BeeLogger
var Logger *log.Logger
func init() {
Log = logs.NewLogger(200)
Log.EnableFuncCallDepth(true)
Log.SetLogFuncCallDepth(Log.GetLogFuncCallDepth() + 1)
Logger = log.New(
log.WithCaller(true),
log.AddCallerSkip(1),
log.WithLevel(log.InfoLevel),
)
}
func InitLog(logFile string, logLevel string, maxdays int64, disableLogColor bool) {
SetLogFile(logFile, maxdays, disableLogColor)
SetLogLevel(logLevel)
}
// SetLogFile to configure log params
func SetLogFile(logFile string, maxdays int64, disableLogColor bool) {
if logFile == "console" {
params := ""
if disableLogColor {
params = `{"color": false}`
func InitLogger(logPath string, levelStr string, maxDays int, disableLogColor bool) {
options := []log.Option{}
if logPath == "console" {
if !disableLogColor {
options = append(options,
log.WithOutput(log.NewConsoleWriter(log.ConsoleConfig{
Colorful: true,
}, os.Stdout)),
)
}
_ = Log.SetLogger("console", params)
} else {
params := fmt.Sprintf(`{"filename": "%s", "maxdays": %d}`, logFile, maxdays)
_ = Log.SetLogger("file", params)
writer := log.NewRotateFileWriter(log.RotateFileConfig{
FileName: logPath,
Mode: log.RotateFileModeDaily,
MaxDays: maxDays,
})
writer.Init()
options = append(options, log.WithOutput(writer))
}
}
// SetLogLevel set log level, default is warning
// value: error, warning, info, debug, trace
func SetLogLevel(logLevel string) {
var level int
switch logLevel {
case "error":
level = 3
case "warn":
level = 4
case "info":
level = 6
case "debug":
level = 7
case "trace":
level = 8
default:
level = 4 // warning
level, err := log.ParseLevel(levelStr)
if err != nil {
level = log.InfoLevel
}
Log.SetLevel(level)
options = append(options, log.WithLevel(level))
Logger = Logger.WithOptions(options...)
}
// wrap log
func Error(format string, v ...interface{}) {
Log.Error(format, v...)
func Errorf(format string, v ...interface{}) {
Logger.Errorf(format, v...)
}
func Warn(format string, v ...interface{}) {
Log.Warn(format, v...)
func Warnf(format string, v ...interface{}) {
Logger.Warnf(format, v...)
}
func Info(format string, v ...interface{}) {
Log.Info(format, v...)
func Infof(format string, v ...interface{}) {
Logger.Infof(format, v...)
}
func Debug(format string, v ...interface{}) {
Log.Debug(format, v...)
func Debugf(format string, v ...interface{}) {
Logger.Debugf(format, v...)
}
func Trace(format string, v ...interface{}) {
Log.Trace(format, v...)
func Tracef(format string, v ...interface{}) {
Logger.Tracef(format, v...)
}

@ -24,30 +24,6 @@ import (
"github.com/fatedier/frp/pkg/util/util"
)
type HTTPAuthWrapper struct {
h http.Handler
user string
passwd string
}
func NewHTTPBasicAuthWrapper(h http.Handler, user, passwd string) http.Handler {
return &HTTPAuthWrapper{
h: h,
user: user,
passwd: passwd,
}
}
func (aw *HTTPAuthWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
user, passwd, hasAuth := r.BasicAuth()
if (aw.user == "" && aw.passwd == "") || (hasAuth && user == aw.user && passwd == aw.passwd) {
aw.h.ServeHTTP(w, r)
} else {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
}
type HTTPAuthMiddleware struct {
user string
passwd string

@ -18,7 +18,7 @@ import (
"fmt"
"net"
kcp "github.com/fatedier/kcp-go"
kcp "github.com/xtaci/kcp-go/v5"
)
type KCPListener struct {
@ -85,7 +85,15 @@ func (l *KCPListener) Addr() net.Addr {
}
func NewKCPConnFromUDP(conn *net.UDPConn, connected bool, raddr string) (net.Conn, error) {
kcpConn, err := kcp.NewConnEx(1, connected, raddr, nil, 10, 3, conn)
udpAddr, err := net.ResolveUDPAddr("udp", raddr)
if err != nil {
return nil, err
}
var pConn net.PacketConn = conn
if connected {
pConn = &ConnectedUDPConn{conn}
}
kcpConn, err := kcp.NewConn3(1, udpAddr, nil, 10, 3, pConn)
if err != nil {
return nil, err
}

@ -4,7 +4,6 @@ import (
"errors"
"net"
"net/http"
"strconv"
"golang.org/x/net/websocket"
)
@ -50,15 +49,6 @@ func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
return
}
func ListenWebsocket(bindAddr string, bindPort int) (*WebsocketListener, error) {
tcpLn, err := net.Listen("tcp", net.JoinHostPort(bindAddr, strconv.Itoa(bindPort)))
if err != nil {
return nil, err
}
l := NewWebsocketListener(tcpLn)
return l, nil
}
func (p *WebsocketListener) Accept() (net.Conn, error) {
c, ok := <-p.acceptCh
if !ok {

@ -47,16 +47,6 @@ func RandIDWithLen(idLen int) (id string, err error) {
return id[:idLen], nil
}
// RandIDWithRandLen return a rand string with length between [start, end).
func RandIDWithRandLen(start, end int) (id string, err error) {
if start >= end {
err = fmt.Errorf("start should be less than end")
return
}
idLen := mathrand.Intn(end-start) + start
return RandIDWithLen(idLen)
}
func GetAuthKey(token string, timestamp int64) (key string) {
md5Ctx := md5.New()
md5Ctx.Write([]byte(token))

@ -14,48 +14,6 @@ func TestRandId(t *testing.T) {
assert.Equal(16, len(id))
}
func TestRandIDWithRandLen(t *testing.T) {
tests := []struct {
name string
start int
end int
expectErr bool
}{
{
name: "start and end are equal",
start: 5,
end: 5,
expectErr: true,
},
{
name: "start is less than end",
start: 5,
end: 10,
expectErr: false,
},
{
name: "start is greater than end",
start: 10,
end: 5,
expectErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
id, err := RandIDWithRandLen(tt.start, tt.end)
if tt.expectErr {
assert.Error(err)
} else {
assert.NoError(err)
assert.GreaterOrEqual(len(id), tt.start)
assert.Less(len(id), tt.end)
}
})
}
}
func TestGetAuthKey(t *testing.T) {
assert := assert.New(t)
key := GetAuthKey("1234", 1488720000)

@ -14,34 +14,8 @@
package version
import (
"strconv"
"strings"
)
var version = "0.54.0"
var version = "0.55.0"
func Full() string {
return version
}
func getSubVersion(v string, position int) int64 {
arr := strings.Split(v, ".")
if len(arr) < 3 {
return 0
}
res, _ := strconv.ParseInt(arr[position], 10, 64)
return res
}
func Proto(v string) int64 {
return getSubVersion(v, 0)
}
func Major(v string) int64 {
return getSubVersion(v, 1)
}
func Minor(v string) int64 {
return getSubVersion(v, 2)
}

@ -1,53 +0,0 @@
// Copyright 2016 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package version
import (
"fmt"
"strconv"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestFull(t *testing.T) {
assert := assert.New(t)
version := Full()
arr := strings.Split(version, ".")
assert.Equal(3, len(arr))
proto, err := strconv.ParseInt(arr[0], 10, 64)
assert.NoError(err)
assert.True(proto >= 0)
major, err := strconv.ParseInt(arr[1], 10, 64)
assert.NoError(err)
assert.True(major >= 0)
minor, err := strconv.ParseInt(arr[2], 10, 64)
assert.NoError(err)
assert.True(minor >= 0)
}
func TestVersion(t *testing.T) {
assert := assert.New(t)
proto := Proto(Full())
major := Major(Full())
minor := Minor(Full())
parseVersion := fmt.Sprintf("%d.%d.%d", proto, major, minor)
version := Full()
assert.Equal(parseVersion, version)
}

@ -20,7 +20,7 @@ import (
"encoding/base64"
"errors"
"fmt"
"log"
stdlog "log"
"net"
"net/http"
"net/http/httputil"
@ -32,7 +32,7 @@ import (
"github.com/fatedier/golib/pool"
httppkg "github.com/fatedier/frp/pkg/util/http"
logpkg "github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/pkg/util/log"
)
var ErrNoRouteFound = errors.New("no route found")
@ -58,7 +58,9 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
}
proxy := &httputil.ReverseProxy{
// Modify incoming requests by route policies.
Director: func(req *http.Request) {
Rewrite: func(r *httputil.ProxyRequest) {
r.SetXForwarded()
req := r.Out
req.URL.Scheme = "http"
reqRouteInfo := req.Context().Value(RouteInfoKey).(*RequestRouteInfo)
oldHost, _ := httppkg.CanonicalHost(reqRouteInfo.Host)
@ -74,7 +76,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
// ignore error here, it will use CreateConnFn instead later
endpoint, _ = rc.ChooseEndpointFn()
reqRouteInfo.Endpoint = endpoint
logpkg.Trace("choose endpoint name [%s] for http request host [%s] path [%s] httpuser [%s]",
log.Tracef("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.
@ -114,9 +116,9 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
},
},
BufferPool: newWrapPool(),
ErrorLog: log.New(newWrapLogger(), "", 0),
ErrorLog: stdlog.New(newWrapLogger(), "", 0),
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
logpkg.Warn("do http proxy request [host: %s] error: %v", req.Host, err)
log.Warnf("do http proxy request [host: %s] error: %v", req.Host, err)
rw.WriteHeader(http.StatusNotFound)
_, _ = rw.Write(getNotFoundPageContent())
},
@ -143,7 +145,7 @@ func (rp *HTTPReverseProxy) UnRegister(routeCfg RouteConfig) {
func (rp *HTTPReverseProxy) GetRouteConfig(domain, location, routeByHTTPUser string) *RouteConfig {
vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
if ok {
logpkg.Debug("get new HTTP request host [%s] path [%s] httpuser [%s]", domain, location, routeByHTTPUser)
log.Debugf("get new HTTP request host [%s] path [%s] httpuser [%s]", domain, location, routeByHTTPUser)
return vr.payload.(*RouteConfig)
}
return nil
@ -333,6 +335,6 @@ type wrapLogger struct{}
func newWrapLogger() *wrapLogger { return &wrapLogger{} }
func (l *wrapLogger) Write(p []byte) (n int, err error) {
logpkg.Warn("%s", string(bytes.TrimRight(p, "\n")))
log.Warnf("%s", string(bytes.TrimRight(p, "\n")))
return len(p), nil
}

@ -20,7 +20,7 @@ import (
"net/http"
"os"
logpkg "github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/pkg/util/version"
)
@ -58,7 +58,7 @@ func getNotFoundPageContent() []byte {
if NotFoundPagePath != "" {
buf, err = os.ReadFile(NotFoundPagePath)
if err != nil {
logpkg.Warn("read custom 404 page error: %v", err)
log.Warnf("read custom 404 page error: %v", err)
buf = []byte(NotFound)
}
} else {

@ -1,8 +1,9 @@
package vhost
import (
"cmp"
"errors"
"sort"
"slices"
"strings"
"sync"
)
@ -58,7 +59,10 @@ func (r *Routers) Add(domain, location, httpUser string, payload interface{}) er
payload: payload,
}
vrs = append(vrs, vr)
sort.Sort(sort.Reverse(ByLocation(vrs)))
slices.SortFunc(vrs, func(a, b *Router) int {
return -cmp.Compare(a.location, b.location)
})
routersByHTTPUser[httpUser] = vrs
r.indexByDomain[domain] = routersByHTTPUser
@ -130,18 +134,3 @@ func (r *Routers) exist(host, path, httpUser string) (route *Router, exist bool)
}
return
}
// sort by location
type ByLocation []*Router
func (a ByLocation) Len() int {
return len(a)
}
func (a ByLocation) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a ByLocation) Less(i, j int) bool {
return strings.Compare(a[i].location, a[j].location) < 0
}

@ -203,7 +203,7 @@ func (v *Muxer) handle(c net.Conn) {
sConn, reqInfoMap, err := v.vhostFunc(c)
if err != nil {
log.Debug("get hostname from http/https request error: %v", err)
log.Debugf("get hostname from http/https request error: %v", err)
_ = c.Close()
return
}
@ -213,7 +213,7 @@ func (v *Muxer) handle(c net.Conn) {
httpUser := reqInfoMap["HTTPUser"]
l, ok := v.getListener(name, path, httpUser)
if !ok {
log.Debug("http request for host [%s] path [%s] httpUser [%s] not found", name, path, httpUser)
log.Debugf("http request for host [%s] path [%s] httpUser [%s] not found", name, path, httpUser)
v.failHook(sConn)
return
}
@ -221,7 +221,7 @@ func (v *Muxer) handle(c net.Conn) {
xl := xlog.FromContextSafe(l.ctx)
if v.successHook != nil {
if err := v.successHook(c, reqInfoMap); err != nil {
xl.Info("success func failure on vhost connection: %v", err)
xl.Infof("success func failure on vhost connection: %v", err)
_ = c.Close()
return
}
@ -232,7 +232,7 @@ func (v *Muxer) handle(c net.Conn) {
if l.mux.checkAuth != nil && l.username != "" {
ok, err := l.mux.checkAuth(c, l.username, l.password, reqInfoMap)
if !ok || err != nil {
xl.Debug("auth failed for user: %s", l.username)
xl.Debugf("auth failed for user: %s", l.username)
_ = c.Close()
return
}
@ -244,12 +244,12 @@ func (v *Muxer) handle(c net.Conn) {
}
c = sConn
xl.Debug("new request host [%s] path [%s] httpUser [%s]", name, path, httpUser)
xl.Debugf("new request host [%s] path [%s] httpUser [%s]", name, path, httpUser)
err = errors.PanicToError(func() {
l.accept <- c
})
if err != nil {
xl.Warn("listener is already closed, ignore this request")
xl.Warnf("listener is already closed, ignore this request")
}
}
@ -278,10 +278,10 @@ func (l *Listener) Accept() (net.Conn, error) {
if l.mux.rewriteHost != nil {
sConn, err := l.mux.rewriteHost(conn, l.rewriteHost)
if err != nil {
xl.Warn("host header rewrite failed: %v", err)
xl.Warnf("host header rewrite failed: %v", err)
return nil, fmt.Errorf("host header rewrite failed")
}
xl.Debug("rewrite host to [%s] success", l.rewriteHost)
xl.Debugf("rewrite host to [%s] success", l.rewriteHost)
conn = sConn
}
return netpkg.NewContextConn(l.ctx, conn), nil

@ -16,7 +16,6 @@ package wait
import (
"math/rand"
"sync"
"time"
"github.com/fatedier/frp/pkg/util/util"
@ -174,21 +173,3 @@ func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
return period
}), true, stopCh)
}
func MergeAndCloseOnAnyStopChannel[T any](upstreams ...<-chan T) <-chan T {
out := make(chan T)
closeOnce := sync.Once{}
for _, upstream := range upstreams {
ch := upstream
go func() {
select {
case <-ch:
closeOnce.Do(func() {
close(out)
})
case <-out:
}
}()
}
return out
}

@ -15,7 +15,8 @@
package xlog
import (
"sort"
"cmp"
"slices"
"github.com/fatedier/frp/pkg/util/log"
)
@ -77,8 +78,8 @@ func (l *Logger) AddPrefix(prefix LogPrefix) *Logger {
}
func (l *Logger) renderPrefixString() {
sort.SliceStable(l.prefixes, func(i, j int) bool {
return l.prefixes[i].Priority < l.prefixes[j].Priority
slices.SortStableFunc(l.prefixes, func(a, b LogPrefix) int {
return cmp.Compare(a.Priority, b.Priority)
})
l.prefixString = ""
for _, v := range l.prefixes {
@ -93,22 +94,22 @@ func (l *Logger) Spawn() *Logger {
return nl
}
func (l *Logger) Error(format string, v ...interface{}) {
log.Log.Error(l.prefixString+format, v...)
func (l *Logger) Errorf(format string, v ...interface{}) {
log.Logger.Errorf(l.prefixString+format, v...)
}
func (l *Logger) Warn(format string, v ...interface{}) {
log.Log.Warn(l.prefixString+format, v...)
func (l *Logger) Warnf(format string, v ...interface{}) {
log.Logger.Warnf(l.prefixString+format, v...)
}
func (l *Logger) Info(format string, v ...interface{}) {
log.Log.Info(l.prefixString+format, v...)
func (l *Logger) Infof(format string, v ...interface{}) {
log.Logger.Infof(l.prefixString+format, v...)
}
func (l *Logger) Debug(format string, v ...interface{}) {
log.Log.Debug(l.prefixString+format, v...)
func (l *Logger) Debugf(format string, v ...interface{}) {
log.Logger.Debugf(l.prefixString+format, v...)
}
func (l *Logger) Trace(format string, v ...interface{}) {
log.Log.Trace(l.prefixString+format, v...)
func (l *Logger) Tracef(format string, v ...interface{}) {
log.Logger.Tracef(l.prefixString+format, v...)
}

@ -224,7 +224,7 @@ func (ctl *Control) Close() error {
func (ctl *Control) Replaced(newCtl *Control) {
xl := ctl.xl
xl.Info("Replaced by client [%s]", newCtl.runID)
xl.Infof("Replaced by client [%s]", newCtl.runID)
ctl.runID = ""
ctl.conn.Close()
}
@ -233,17 +233,17 @@ func (ctl *Control) RegisterWorkConn(conn net.Conn) error {
xl := ctl.xl
defer func() {
if err := recover(); err != nil {
xl.Error("panic error: %v", err)
xl.Error(string(debug.Stack()))
xl.Errorf("panic error: %v", err)
xl.Errorf(string(debug.Stack()))
}
}()
select {
case ctl.workConnCh <- conn:
xl.Debug("new work connection registered")
xl.Debugf("new work connection registered")
return nil
default:
xl.Debug("work connection pool is full, discarding")
xl.Debugf("work connection pool is full, discarding")
return fmt.Errorf("work connection pool is full, discarding")
}
}
@ -256,8 +256,8 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
xl := ctl.xl
defer func() {
if err := recover(); err != nil {
xl.Error("panic error: %v", err)
xl.Error(string(debug.Stack()))
xl.Errorf("panic error: %v", err)
xl.Errorf(string(debug.Stack()))
}
}()
@ -269,7 +269,7 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
err = pkgerr.ErrCtlClosed
return
}
xl.Debug("get work connection from pool")
xl.Debugf("get work connection from pool")
default:
// no work connections available in the poll, send message to frpc to get more
if err := ctl.msgDispatcher.Send(&msg.ReqWorkConn{}); err != nil {
@ -280,13 +280,13 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
case workConn, ok = <-ctl.workConnCh:
if !ok {
err = pkgerr.ErrCtlClosed
xl.Warn("no work connections available, %v", err)
xl.Warnf("no work connections available, %v", err)
return
}
case <-time.After(time.Duration(ctl.serverCfg.UserConnTimeout) * time.Second):
err = fmt.Errorf("timeout trying to get work connection")
xl.Warn("%v", err)
xl.Warnf("%v", err)
return
}
}
@ -305,7 +305,7 @@ func (ctl *Control) heartbeatWorker() {
if !lo.FromPtr(ctl.serverCfg.Transport.TCPMux) && ctl.serverCfg.Transport.HeartbeatTimeout > 0 {
go wait.Until(func() {
if time.Since(ctl.lastPing.Load().(time.Time)) > time.Duration(ctl.serverCfg.Transport.HeartbeatTimeout)*time.Second {
xl.Warn("heartbeat timeout")
xl.Warnf("heartbeat timeout")
ctl.conn.Close()
return
}
@ -356,7 +356,7 @@ func (ctl *Control) worker() {
}
metrics.Server.CloseClient()
xl.Info("client exit success")
xl.Infof("client exit success")
close(ctl.doneCh)
}
@ -393,12 +393,12 @@ func (ctl *Control) handleNewProxy(m msg.Message) {
ProxyName: inMsg.ProxyName,
}
if err != nil {
xl.Warn("new proxy [%s] type [%s] error: %v", inMsg.ProxyName, inMsg.ProxyType, err)
xl.Warnf("new proxy [%s] type [%s] error: %v", inMsg.ProxyName, inMsg.ProxyType, err)
resp.Error = util.GenerateResponseErrorString(fmt.Sprintf("new proxy [%s] error", inMsg.ProxyName),
err, lo.FromPtr(ctl.serverCfg.DetailedErrorsToClient))
} else {
resp.RemoteAddr = remoteAddr
xl.Info("new proxy [%s] type [%s] success", inMsg.ProxyName, inMsg.ProxyType)
xl.Infof("new proxy [%s] type [%s] success", inMsg.ProxyName, inMsg.ProxyType)
metrics.Server.NewProxy(inMsg.ProxyName, inMsg.ProxyType)
}
_ = ctl.msgDispatcher.Send(resp)
@ -422,14 +422,14 @@ func (ctl *Control) handlePing(m msg.Message) {
err = ctl.authVerifier.VerifyPing(inMsg)
}
if err != nil {
xl.Warn("received invalid ping: %v", err)
xl.Warnf("received invalid ping: %v", err)
_ = ctl.msgDispatcher.Send(&msg.Pong{
Error: util.GenerateResponseErrorString("invalid ping", err, lo.FromPtr(ctl.serverCfg.DetailedErrorsToClient)),
})
return
}
ctl.lastPing.Store(time.Now())
xl.Debug("receive heartbeat")
xl.Debugf("receive heartbeat")
_ = ctl.msgDispatcher.Send(&msg.Pong{})
}
@ -452,7 +452,7 @@ func (ctl *Control) handleCloseProxy(m msg.Message) {
xl := ctl.xl
inMsg := m.(*msg.CloseProxy)
_ = ctl.CloseProxy(inMsg)
xl.Info("close proxy [%s] success", inMsg.ProxyName)
xl.Infof("close proxy [%s] success", inMsg.ProxyName)
}
func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err error) {

@ -15,9 +15,10 @@
package server
import (
"cmp"
"encoding/json"
"net/http"
"sort"
"slices"
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus/promhttp"
@ -98,14 +99,14 @@ func (svr *Service) healthz(w http.ResponseWriter, _ *http.Request) {
func (svr *Service) apiServerInfo(w http.ResponseWriter, r *http.Request) {
res := GeneralResponse{Code: 200}
defer func() {
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
log.Infof("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
}
}()
log.Info("Http request: [%s]", r.URL.Path)
log.Infof("Http request: [%s]", r.URL.Path)
serverStats := mem.StatsCollector.GetServer()
svrResp := serverInfoResp{
Version: version.Full(),
@ -218,18 +219,18 @@ func (svr *Service) apiProxyByType(w http.ResponseWriter, r *http.Request) {
proxyType := params["type"]
defer func() {
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
log.Infof("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
}
}()
log.Info("Http request: [%s]", r.URL.Path)
log.Infof("Http request: [%s]", r.URL.Path)
proxyInfoResp := GetProxyInfoResp{}
proxyInfoResp.Proxies = svr.getProxyStatsByType(proxyType)
sort.Slice(proxyInfoResp.Proxies, func(i, j int) bool {
return proxyInfoResp.Proxies[i].Name < proxyInfoResp.Proxies[j].Name
slices.SortFunc(proxyInfoResp.Proxies, func(a, b *ProxyStatsInfo) int {
return cmp.Compare(a.Name, b.Name)
})
buf, _ := json.Marshal(&proxyInfoResp)
@ -244,12 +245,12 @@ func (svr *Service) getProxyStatsByType(proxyType string) (proxyInfos []*ProxySt
if pxy, ok := svr.pxyManager.GetByName(ps.Name); ok {
content, err := json.Marshal(pxy.GetConfigurer())
if err != nil {
log.Warn("marshal proxy [%s] conf info error: %v", ps.Name, err)
log.Warnf("marshal proxy [%s] conf info error: %v", ps.Name, err)
continue
}
proxyInfo.Conf = getConfByType(ps.Type)
if err = json.Unmarshal(content, &proxyInfo.Conf); err != nil {
log.Warn("unmarshal proxy [%s] conf info error: %v", ps.Name, err)
log.Warnf("unmarshal proxy [%s] conf info error: %v", ps.Name, err)
continue
}
proxyInfo.Status = "online"
@ -290,13 +291,13 @@ func (svr *Service) apiProxyByTypeAndName(w http.ResponseWriter, r *http.Request
name := params["name"]
defer func() {
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
log.Infof("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
}
}()
log.Info("Http request: [%s]", r.URL.Path)
log.Infof("Http request: [%s]", r.URL.Path)
var proxyStatsResp GetProxyStatsResp
proxyStatsResp, res.Code, res.Msg = svr.getProxyStatsByTypeAndName(proxyType, name)
@ -318,14 +319,14 @@ func (svr *Service) getProxyStatsByTypeAndName(proxyType string, proxyName strin
if pxy, ok := svr.pxyManager.GetByName(proxyName); ok {
content, err := json.Marshal(pxy.GetConfigurer())
if err != nil {
log.Warn("marshal proxy [%s] conf info error: %v", ps.Name, err)
log.Warnf("marshal proxy [%s] conf info error: %v", ps.Name, err)
code = 400
msg = "parse conf error"
return
}
proxyInfo.Conf = getConfByType(ps.Type)
if err = json.Unmarshal(content, &proxyInfo.Conf); err != nil {
log.Warn("unmarshal proxy [%s] conf info error: %v", ps.Name, err)
log.Warnf("unmarshal proxy [%s] conf info error: %v", ps.Name, err)
code = 400
msg = "parse conf error"
return
@ -358,13 +359,13 @@ func (svr *Service) apiProxyTraffic(w http.ResponseWriter, r *http.Request) {
name := params["name"]
defer func() {
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
log.Infof("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
}
}()
log.Info("Http request: [%s]", r.URL.Path)
log.Infof("Http request: [%s]", r.URL.Path)
trafficResp := GetProxyTrafficResp{}
trafficResp.Name = name
@ -386,9 +387,9 @@ func (svr *Service) apiProxyTraffic(w http.ResponseWriter, r *http.Request) {
func (svr *Service) deleteProxies(w http.ResponseWriter, r *http.Request) {
res := GeneralResponse{Code: 200}
log.Info("Http request: [%s]", r.URL.Path)
log.Infof("Http request: [%s]", r.URL.Path)
defer func() {
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
log.Infof("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
_, _ = w.Write([]byte(res.Msg))
@ -402,5 +403,5 @@ func (svr *Service) deleteProxies(w http.ResponseWriter, r *http.Request) {
return
}
cleared, total := mem.StatsCollector.ClearOfflineProxies()
log.Info("cleared [%d] offline proxies, total [%d] proxies", cleared, total)
log.Infof("cleared [%d] offline proxies, total [%d] proxies", cleared, total)
}

@ -107,7 +107,7 @@ func (pxy *HTTPProxy) Run() (remoteAddr string, err error) {
})
}
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.Infof("http proxy listen for host [%s] location [%s] group [%s], routeByHTTPUser [%s]",
routeConfig.Domain, routeConfig.Location, pxy.cfg.LoadBalancer.Group, pxy.cfg.RouteByHTTPUser)
}
}
@ -140,7 +140,7 @@ func (pxy *HTTPProxy) Run() (remoteAddr string, err error) {
}
addrs = append(addrs, util.CanonicalAddr(tmpRouteConfig.Domain, pxy.serverCfg.VhostHTTPPort))
xl.Info("http proxy listen for host [%s] location [%s] group [%s], routeByHTTPUser [%s]",
xl.Infof("http proxy listen for host [%s] location [%s] group [%s], routeByHTTPUser [%s]",
routeConfig.Domain, routeConfig.Location, pxy.cfg.LoadBalancer.Group, pxy.cfg.RouteByHTTPUser)
}
}
@ -152,7 +152,7 @@ func (pxy *HTTPProxy) GetRealConn(remoteAddr string) (workConn net.Conn, err err
xl := pxy.xl
rAddr, errRet := net.ResolveTCPAddr("tcp", remoteAddr)
if errRet != nil {
xl.Warn("resolve TCP addr [%s] error: %v", remoteAddr, errRet)
xl.Warnf("resolve TCP addr [%s] error: %v", remoteAddr, errRet)
// we do not return error here since remoteAddr is not necessary for proxies without proxy protocol enabled
}
@ -166,7 +166,7 @@ func (pxy *HTTPProxy) GetRealConn(remoteAddr string) (workConn net.Conn, err err
if pxy.cfg.Transport.UseEncryption {
rwc, err = libio.WithEncryption(rwc, []byte(pxy.serverCfg.Auth.Token))
if err != nil {
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
return
}
}

@ -64,7 +64,7 @@ func (pxy *HTTPSProxy) Run() (remoteAddr string, err error) {
err = errRet
return
}
xl.Info("https proxy listen for host [%s]", routeConfig.Domain)
xl.Infof("https proxy listen for host [%s]", routeConfig.Domain)
pxy.listeners = append(pxy.listeners, l)
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, pxy.serverCfg.VhostHTTPSPort))
}
@ -76,7 +76,7 @@ func (pxy *HTTPSProxy) Run() (remoteAddr string, err error) {
err = errRet
return
}
xl.Info("https proxy listen for host [%s]", routeConfig.Domain)
xl.Infof("https proxy listen for host [%s]", routeConfig.Domain)
pxy.listeners = append(pxy.listeners, l)
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, pxy.serverCfg.VhostHTTPSPort))
}

@ -112,7 +112,7 @@ func (pxy *BaseProxy) GetConfigurer() v1.ProxyConfigurer {
func (pxy *BaseProxy) Close() {
xl := xlog.FromContextSafe(pxy.ctx)
xl.Info("proxy closing")
xl.Infof("proxy closing")
for _, l := range pxy.listeners {
l.Close()
}
@ -125,10 +125,10 @@ func (pxy *BaseProxy) GetWorkConnFromPool(src, dst net.Addr) (workConn net.Conn,
// try all connections from the pool
for i := 0; i < pxy.poolCount+1; i++ {
if workConn, err = pxy.getWorkConnFn(); err != nil {
xl.Warn("failed to get work connection: %v", err)
xl.Warnf("failed to get work connection: %v", err)
return
}
xl.Debug("get a new work connection: [%s]", workConn.RemoteAddr().String())
xl.Debugf("get a new work connection: [%s]", workConn.RemoteAddr().String())
xl.Spawn().AppendPrefix(pxy.GetName())
workConn = netpkg.NewContextConn(pxy.ctx, workConn)
@ -158,7 +158,7 @@ func (pxy *BaseProxy) GetWorkConnFromPool(src, dst net.Addr) (workConn net.Conn,
Error: "",
})
if err != nil {
xl.Warn("failed to send message to work connection from pool: %v, times: %d", err, i)
xl.Warnf("failed to send message to work connection from pool: %v, times: %d", err, i)
workConn.Close()
} else {
break
@ -166,7 +166,7 @@ func (pxy *BaseProxy) GetWorkConnFromPool(src, dst net.Addr) (workConn net.Conn,
}
if err != nil {
xl.Error("try to get work connection failed in the end")
xl.Errorf("try to get work connection failed in the end")
return
}
return
@ -193,15 +193,15 @@ func (pxy *BaseProxy) startCommonTCPListenersHandler() {
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
xl.Info("met temporary error: %s, sleep for %s ...", err, tempDelay)
xl.Infof("met temporary error: %s, sleep for %s ...", err, tempDelay)
time.Sleep(tempDelay)
continue
}
xl.Warn("listener is closed: %s", err)
xl.Warnf("listener is closed: %s", err)
return
}
xl.Info("get a user connection [%s]", c.RemoteAddr().String())
xl.Infof("get a user connection [%s]", c.RemoteAddr().String())
go pxy.handleUserTCPConnection(c)
}
}(listener)
@ -225,7 +225,7 @@ func (pxy *BaseProxy) handleUserTCPConnection(userConn net.Conn) {
}
_, err := rc.PluginManager.NewUserConn(content)
if err != nil {
xl.Warn("the user conn [%s] was rejected, err:%v", content.RemoteAddr, err)
xl.Warnf("the user conn [%s] was rejected, err:%v", content.RemoteAddr, err)
return
}
@ -237,12 +237,12 @@ func (pxy *BaseProxy) handleUserTCPConnection(userConn net.Conn) {
defer workConn.Close()
var local io.ReadWriteCloser = workConn
xl.Trace("handler user tcp connection, use_encryption: %t, use_compression: %t",
xl.Tracef("handler user tcp connection, use_encryption: %t, use_compression: %t",
cfg.Transport.UseEncryption, cfg.Transport.UseCompression)
if cfg.Transport.UseEncryption {
local, err = libio.WithEncryption(local, []byte(serverCfg.Auth.Token))
if err != nil {
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
return
}
}
@ -258,7 +258,7 @@ func (pxy *BaseProxy) handleUserTCPConnection(userConn net.Conn) {
})
}
xl.Debug("join connections, workConn(l[%s] r[%s]) userConn(l[%s] r[%s])", workConn.LocalAddr().String(),
xl.Debugf("join connections, workConn(l[%s] r[%s]) userConn(l[%s] r[%s])", workConn.LocalAddr().String(),
workConn.RemoteAddr().String(), userConn.LocalAddr().String(), userConn.RemoteAddr().String())
name := pxy.GetName()
@ -268,7 +268,7 @@ func (pxy *BaseProxy) handleUserTCPConnection(userConn net.Conn) {
metrics.Server.CloseConnection(name, proxyType)
metrics.Server.AddTrafficIn(name, proxyType, inCount)
metrics.Server.AddTrafficOut(name, proxyType, outCount)
xl.Debug("join connections closed")
xl.Debugf("join connections closed")
}
type Options struct {

@ -53,7 +53,7 @@ func (pxy *STCPProxy) Run() (remoteAddr string, err error) {
return
}
pxy.listeners = append(pxy.listeners, listener)
xl.Info("stcp proxy custom listen success")
xl.Infof("stcp proxy custom listen success")
pxy.startCommonTCPListenersHandler()
return

@ -53,7 +53,7 @@ func (pxy *SUDPProxy) Run() (remoteAddr string, err error) {
return
}
pxy.listeners = append(pxy.listeners, listener)
xl.Info("sudp proxy custom listen success")
xl.Infof("sudp proxy custom listen success")
pxy.startCommonTCPListenersHandler()
return

@ -62,7 +62,7 @@ func (pxy *TCPProxy) Run() (remoteAddr string, err error) {
}()
pxy.realBindPort = realBindPort
pxy.listeners = append(pxy.listeners, l)
xl.Info("tcp proxy listen port [%d] in group [%s]", pxy.cfg.RemotePort, pxy.cfg.LoadBalancer.Group)
xl.Infof("tcp proxy listen port [%d] in group [%s]", pxy.cfg.RemotePort, pxy.cfg.LoadBalancer.Group)
} else {
pxy.realBindPort, err = pxy.rc.TCPPortManager.Acquire(pxy.name, pxy.cfg.RemotePort)
if err != nil {
@ -79,7 +79,7 @@ func (pxy *TCPProxy) Run() (remoteAddr string, err error) {
return
}
pxy.listeners = append(pxy.listeners, listener)
xl.Info("tcp proxy listen port [%d]", pxy.cfg.RemotePort)
xl.Infof("tcp proxy listen port [%d]", pxy.cfg.RemotePort)
}
pxy.cfg.RemotePort = pxy.realBindPort

@ -65,7 +65,7 @@ func (pxy *TCPMuxProxy) httpConnectListen(
if err != nil {
return nil, err
}
pxy.xl.Info("tcpmux httpconnect multiplexer listens for host [%s], group [%s] routeByHTTPUser [%s]",
pxy.xl.Infof("tcpmux httpconnect multiplexer listens for host [%s], group [%s] routeByHTTPUser [%s]",
domain, pxy.cfg.LoadBalancer.Group, pxy.cfg.RouteByHTTPUser)
pxy.listeners = append(pxy.listeners, l)
return append(addrs, util.CanonicalAddr(domain, pxy.serverCfg.TCPMuxHTTPConnectPort)), nil

@ -97,10 +97,10 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
udpConn, errRet := net.ListenUDP("udp", addr)
if errRet != nil {
err = errRet
xl.Warn("listen udp port error: %v", err)
xl.Warnf("listen udp port error: %v", err)
return
}
xl.Info("udp proxy listen port [%d]", pxy.cfg.RemotePort)
xl.Infof("udp proxy listen port [%d]", pxy.cfg.RemotePort)
pxy.udpConn = udpConn
pxy.sendCh = make(chan *msg.UDPPacket, 1024)
@ -114,11 +114,11 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
rawMsg msg.Message
errRet error
)
xl.Trace("loop waiting message from udp workConn")
xl.Tracef("loop waiting message from udp workConn")
// client will send heartbeat in workConn for keeping alive
_ = conn.SetReadDeadline(time.Now().Add(time.Duration(60) * time.Second))
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
xl.Warn("read from workConn for udp error: %v", errRet)
xl.Warnf("read from workConn for udp error: %v", errRet)
_ = conn.Close()
// notify proxy to start a new work connection
// ignore error here, it means the proxy is closed
@ -128,15 +128,15 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
return
}
if err := conn.SetReadDeadline(time.Time{}); err != nil {
xl.Warn("set read deadline error: %v", err)
xl.Warnf("set read deadline error: %v", err)
}
switch m := rawMsg.(type) {
case *msg.Ping:
xl.Trace("udp work conn get ping message")
xl.Tracef("udp work conn get ping message")
continue
case *msg.UDPPacket:
if errRet := errors.PanicToError(func() {
xl.Trace("get udp message from workConn: %s", m.Content)
xl.Tracef("get udp message from workConn: %s", m.Content)
pxy.readCh <- m
metrics.Server.AddTrafficOut(
pxy.GetName(),
@ -145,7 +145,7 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
)
}); errRet != nil {
conn.Close()
xl.Info("reader goroutine for udp work connection closed")
xl.Infof("reader goroutine for udp work connection closed")
return
}
}
@ -159,15 +159,15 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
select {
case udpMsg, ok := <-pxy.sendCh:
if !ok {
xl.Info("sender goroutine for udp work connection closed")
xl.Infof("sender goroutine for udp work connection closed")
return
}
if errRet = msg.WriteMsg(conn, udpMsg); errRet != nil {
xl.Info("sender goroutine for udp work connection closed: %v", errRet)
xl.Infof("sender goroutine for udp work connection closed: %v", errRet)
conn.Close()
return
}
xl.Trace("send message to udp workConn: %s", udpMsg.Content)
xl.Tracef("send message to udp workConn: %s", udpMsg.Content)
metrics.Server.AddTrafficIn(
pxy.GetName(),
pxy.GetConfigurer().GetBaseConfig().Type,
@ -175,7 +175,7 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
)
continue
case <-ctx.Done():
xl.Info("sender goroutine for udp work connection closed")
xl.Infof("sender goroutine for udp work connection closed")
return
}
}
@ -207,7 +207,7 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
if pxy.cfg.Transport.UseEncryption {
rwc, err = libio.WithEncryption(rwc, []byte(pxy.serverCfg.Auth.Token))
if err != nil {
xl.Error("create encryption stream error: %v", err)
xl.Errorf("create encryption stream error: %v", err)
workConn.Close()
continue
}

@ -77,7 +77,7 @@ func (pxy *XTCPProxy) Run() (remoteAddr string, err error) {
}
errRet = msg.WriteMsg(workConn, m)
if errRet != nil {
xl.Warn("write nat hole sid package error, %v", errRet)
xl.Warnf("write nat hole sid package error, %v", errRet)
}
workConn.Close()
}

@ -172,13 +172,13 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
if err != nil {
return nil, fmt.Errorf("create vhost tcpMuxer error, %v", err)
}
log.Info("tcpmux httpconnect multiplexer listen on %s, passthough: %v", address, cfg.TCPMuxPassthrough)
log.Infof("tcpmux httpconnect multiplexer listen on %s, passthough: %v", address, cfg.TCPMuxPassthrough)
}
// Init all plugins
for _, p := range cfg.HTTPPlugins {
svr.pluginManager.Register(plugin.NewHTTPPluginOptions(p))
log.Info("plugin [%s] has been registered", p.Name)
log.Infof("plugin [%s] has been registered", p.Name)
}
svr.rc.PluginManager = svr.pluginManager
@ -222,7 +222,7 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
ln = svr.muxer.DefaultListener()
svr.listener = ln
log.Info("frps tcp listen on %s", address)
log.Infof("frps tcp listen on %s", address)
// Listen for accepting connections from client using kcp protocol.
if cfg.KCPBindPort > 0 {
@ -231,7 +231,7 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
if err != nil {
return nil, fmt.Errorf("listen on kcp udp address %s error: %v", address, err)
}
log.Info("frps kcp listen on udp %s", address)
log.Infof("frps kcp listen on udp %s", address)
}
if cfg.QUICBindPort > 0 {
@ -246,7 +246,7 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
if err != nil {
return nil, fmt.Errorf("listen on quic udp address %s error: %v", address, err)
}
log.Info("frps quic listen on %s", address)
log.Infof("frps quic listen on %s", address)
}
if cfg.SSHTunnelGateway.BindPort > 0 {
@ -255,7 +255,7 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
return nil, fmt.Errorf("create ssh gateway error: %v", err)
}
svr.sshTunnelGateway = sshGateway
log.Info("frps sshTunnelGateway listen on port %d", cfg.SSHTunnelGateway.BindPort)
log.Infof("frps sshTunnelGateway listen on port %d", cfg.SSHTunnelGateway.BindPort)
}
// Listen for accepting connections from client using websocket protocol.
@ -289,7 +289,7 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
go func() {
_ = server.Serve(l)
}()
log.Info("http service listen on %s", address)
log.Infof("http service listen on %s", address)
}
// Create https vhost muxer.
@ -303,7 +303,7 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
if err != nil {
return nil, fmt.Errorf("create server listener error, %v", err)
}
log.Info("https service listen on %s", address)
log.Infof("https service listen on %s", address)
}
svr.rc.VhostHTTPSMuxer, err = vhost.NewHTTPSMuxer(l, vhostReadWriteTimeout)
@ -335,9 +335,9 @@ func (svr *Service) Run(ctx context.Context) {
// run dashboard web server.
if svr.webServer != nil {
go func() {
log.Info("dashboard listen on %s", svr.webServer.Address())
log.Infof("dashboard listen on %s", svr.webServer.Address())
if err := svr.webServer.Run(); err != nil {
log.Warn("dashboard server exit with error: %v", err)
log.Warnf("dashboard server exit with error: %v", err)
}
}()
}
@ -408,7 +408,7 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn, interna
_ = conn.SetReadDeadline(time.Now().Add(connReadTimeout))
if rawMsg, err = msg.ReadMsg(conn); err != nil {
log.Trace("Failed to read message: %v", err)
log.Tracef("Failed to read message: %v", err)
conn.Close()
return
}
@ -430,7 +430,7 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn, interna
// If login failed, send error message there.
// Otherwise send success message in control's work goroutine.
if err != nil {
xl.Warn("register control error: %v", err)
xl.Warnf("register control error: %v", err)
_ = msg.WriteMsg(conn, &msg.LoginResp{
Version: version.Full(),
Error: util.GenerateResponseErrorString("register control error", err, lo.FromPtr(svr.cfg.DetailedErrorsToClient)),
@ -443,7 +443,7 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn, interna
}
case *msg.NewVisitorConn:
if err = svr.RegisterVisitorConn(conn, m); err != nil {
xl.Warn("register visitor conn error: %v", err)
xl.Warnf("register visitor conn error: %v", err)
_ = msg.WriteMsg(conn, &msg.NewVisitorConnResp{
ProxyName: m.ProxyName,
Error: util.GenerateResponseErrorString("register visitor conn error", err, lo.FromPtr(svr.cfg.DetailedErrorsToClient)),
@ -456,7 +456,7 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn, interna
})
}
default:
log.Warn("Error message type for the new connection [%s]", conn.RemoteAddr().String())
log.Warnf("Error message type for the new connection [%s]", conn.RemoteAddr().String())
conn.Close()
}
}
@ -469,7 +469,7 @@ func (svr *Service) HandleListener(l net.Listener, internal bool) {
for {
c, err := l.Accept()
if err != nil {
log.Warn("Listener for incoming connections from client closed")
log.Warnf("Listener for incoming connections from client closed")
return
}
// inject xlog object into net.Conn context
@ -479,17 +479,17 @@ func (svr *Service) HandleListener(l net.Listener, internal bool) {
c = netpkg.NewContextConn(xlog.NewContext(ctx, xl), c)
if !internal {
log.Trace("start check TLS connection...")
log.Tracef("start check TLS connection...")
originConn := c
forceTLS := svr.cfg.Transport.TLS.Force
var isTLS, custom bool
c, isTLS, custom, err = netpkg.CheckAndEnableTLSServerConnWithTimeout(c, svr.tlsConfig, forceTLS, connReadTimeout)
if err != nil {
log.Warn("CheckAndEnableTLSServerConnWithTimeout error: %v", err)
log.Warnf("CheckAndEnableTLSServerConnWithTimeout error: %v", err)
originConn.Close()
continue
}
log.Trace("check TLS connection success, isTLS: %v custom: %v internal: %v", isTLS, custom, internal)
log.Tracef("check TLS connection success, isTLS: %v custom: %v internal: %v", isTLS, custom, internal)
}
// Start a new goroutine to handle connection.
@ -501,7 +501,7 @@ func (svr *Service) HandleListener(l net.Listener, internal bool) {
fmuxCfg.MaxStreamWindowSize = 6 * 1024 * 1024
session, err := fmux.Server(frpConn, fmuxCfg)
if err != nil {
log.Warn("Failed to create mux connection: %v", err)
log.Warnf("Failed to create mux connection: %v", err)
frpConn.Close()
return
}
@ -509,7 +509,7 @@ func (svr *Service) HandleListener(l net.Listener, internal bool) {
for {
stream, err := session.AcceptStream()
if err != nil {
log.Debug("Accept new mux stream error: %v", err)
log.Debugf("Accept new mux stream error: %v", err)
session.Close()
return
}
@ -527,7 +527,7 @@ func (svr *Service) HandleQUICListener(l *quic.Listener) {
for {
c, err := l.Accept(context.Background())
if err != nil {
log.Warn("QUICListener for incoming connections from client closed")
log.Warnf("QUICListener for incoming connections from client closed")
return
}
// Start a new goroutine to handle connection.
@ -535,7 +535,7 @@ func (svr *Service) HandleQUICListener(l *quic.Listener) {
for {
stream, err := frpConn.AcceptStream(context.Background())
if err != nil {
log.Debug("Accept new quic mux stream error: %v", err)
log.Debugf("Accept new quic mux stream error: %v", err)
_ = frpConn.CloseWithError(0, "")
return
}
@ -560,7 +560,7 @@ func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login, inter
xl := xlog.FromContextSafe(ctx)
xl.AppendPrefix(loginMsg.RunID)
ctx = xlog.NewContext(ctx, xl)
xl.Info("client login info: ip [%s] version [%s] hostname [%s] os [%s] arch [%s]",
xl.Infof("client login info: ip [%s] version [%s] hostname [%s] os [%s] arch [%s]",
ctlConn.RemoteAddr().String(), loginMsg.Version, loginMsg.Hostname, loginMsg.Os, loginMsg.Arch)
// Check auth.
@ -575,7 +575,7 @@ func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login, inter
// TODO(fatedier): use SessionContext
ctl, err := NewControl(ctx, svr.rc, svr.pxyManager, svr.pluginManager, authVerifier, ctlConn, !internal, loginMsg, svr.cfg)
if err != nil {
xl.Warn("create new controller error: %v", err)
xl.Warnf("create new controller error: %v", err)
// don't return detailed errors to client
return fmt.Errorf("unexpected error when creating new controller")
}
@ -601,7 +601,7 @@ func (svr *Service) RegisterWorkConn(workConn net.Conn, newMsg *msg.NewWorkConn)
xl := netpkg.NewLogFromConn(workConn)
ctl, exist := svr.ctlManager.GetByID(newMsg.RunID)
if !exist {
xl.Warn("No client control found for run id [%s]", newMsg.RunID)
xl.Warnf("No client control found for run id [%s]", newMsg.RunID)
return fmt.Errorf("no client control found for run id [%s]", newMsg.RunID)
}
// server plugin hook
@ -620,7 +620,7 @@ func (svr *Service) RegisterWorkConn(workConn net.Conn, newMsg *msg.NewWorkConn)
err = ctl.authVerifier.VerifyNewWorkConn(newMsg)
}
if err != nil {
xl.Warn("invalid NewWorkConn with run id [%s]", newMsg.RunID)
xl.Warnf("invalid NewWorkConn with run id [%s]", newMsg.RunID)
_ = msg.WriteMsg(workConn, &msg.StartWorkConn{
Error: util.GenerateResponseErrorString("invalid NewWorkConn", err, lo.FromPtr(svr.cfg.DetailedErrorsToClient)),
})

@ -18,10 +18,10 @@ import (
"fmt"
"io"
"net"
"slices"
"sync"
libio "github.com/fatedier/golib/io"
"github.com/samber/lo"
netpkg "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/pkg/util/util"
@ -75,7 +75,7 @@ func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey
return
}
if !lo.Contains(l.allowUsers, visitorUser) && !lo.Contains(l.allowUsers, "*") {
if !slices.Contains(l.allowUsers, visitorUser) && !slices.Contains(l.allowUsers, "*") {
err = fmt.Errorf("visitor connection of [%s] user [%s] not allowed", name, visitorUser)
return
}

@ -38,7 +38,7 @@ func RunE2ETests(t *testing.T) {
// Randomize specs as well as suites
suiteConfig.RandomizeAllSpecs = true
log.Info("Starting e2e run %q on Ginkgo node %d of total %d",
log.Infof("Starting e2e run %q on Ginkgo node %d of total %d",
framework.RunID, suiteConfig.ParallelProcess, suiteConfig.ParallelTotal)
ginkgo.RunSpecs(t, "frp e2e suite", suiteConfig, reporterConfig)
}

@ -34,7 +34,7 @@ func TestMain(m *testing.M) {
os.Exit(1)
}
log.InitLog("console", framework.TestContext.LogLevel, 0, true)
log.InitLogger("console", framework.TestContext.LogLevel, 0, true)
os.Exit(m.Run())
}

@ -31,7 +31,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
ExpectNoError(err)
if TestContext.Debug {
flog.Debug("[%s] %s", path, outs[i])
flog.Debugf("[%s] %s", path, outs[i])
}
p := process.NewWithEnvs(TestContext.FRPServerPath, []string{"-c", path}, f.osEnvs)
@ -52,7 +52,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
ExpectNoError(err)
if TestContext.Debug {
flog.Debug("[%s] %s", path, outs[index])
flog.Debugf("[%s] %s", path, outs[index])
}
p := process.NewWithEnvs(TestContext.FRPClientPath, []string{"-c", path}, f.osEnvs)

@ -20,7 +20,7 @@ func ExpectResponseCode(code int) EnsureFunc {
if resp.Code == code {
return true
}
flog.Warn("Expect code %d, but got %d", code, resp.Code)
flog.Warnf("Expect code %d, but got %d", code, resp.Code)
return false
}
}
@ -111,14 +111,14 @@ func (e *RequestExpect) Ensure(fns ...EnsureFunc) {
if len(fns) == 0 {
if !bytes.Equal(e.expectResp, ret.Content) {
flog.Trace("Response info: %+v", ret)
flog.Tracef("Response info: %+v", ret)
}
ExpectEqualValuesWithOffset(1, ret.Content, e.expectResp, e.explain...)
} else {
for _, fn := range fns {
ok := fn(ret)
if !ok {
flog.Trace("Response info: %+v", ret)
flog.Tracef("Response info: %+v", ret)
}
ExpectTrueWithOffset(1, ok, e.explain...)
}

@ -41,7 +41,7 @@ var _ = ginkgo.Describe("[Feature: Monitor]", func() {
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
r.HTTP().Port(dashboardPort).HTTPPath("/metrics")
}).Ensure(func(resp *request.Response) bool {
log.Trace("prometheus metrics response: \n%s", resp.Content)
log.Tracef("prometheus metrics response: \n%s", resp.Content)
if resp.Code != 200 {
return false
}

@ -66,7 +66,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
rd := bufio.NewReader(c)
ppHeader, err := pp.Read(rd)
if err != nil {
log.Error("read proxy protocol error: %v", err)
log.Errorf("read proxy protocol error: %v", err)
return
}
@ -93,7 +93,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
f.RunProcesses([]string{serverConf}, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure(func(resp *request.Response) bool {
log.Trace("ProxyProtocol get SourceAddr: %s", string(resp.Content))
log.Tracef("ProxyProtocol get SourceAddr: %s", string(resp.Content))
addr, err := net.ResolveTCPAddr("tcp", string(resp.Content))
if err != nil {
return false
@ -121,7 +121,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
rd := bufio.NewReader(c)
ppHeader, err := pp.Read(rd)
if err != nil {
log.Error("read proxy protocol error: %v", err)
log.Errorf("read proxy protocol error: %v", err)
return
}
srcAddrRecord = ppHeader.SourceAddr.String()
@ -142,7 +142,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
r.HTTP().HTTPHost("normal.example.com")
}).Ensure(framework.ExpectResponseCode(404))
log.Trace("ProxyProtocol get SourceAddr: %s", srcAddrRecord)
log.Tracef("ProxyProtocol get SourceAddr: %s", srcAddrRecord)
addr, err := net.ResolveTCPAddr("tcp", srcAddrRecord)
framework.ExpectNoError(err, srcAddrRecord)
framework.ExpectEqualValues("127.0.0.1", addr.IP.String())

@ -26,7 +26,7 @@ func NewHTTPPluginServer(port int, newFunc NewPluginRequest, handler Handler, tl
w.WriteHeader(500)
return
}
log.Trace("plugin request: %s", string(buf))
log.Tracef("plugin request: %s", string(buf))
err = json.Unmarshal(buf, &r)
if err != nil {
w.WriteHeader(500)
@ -34,7 +34,7 @@ func NewHTTPPluginServer(port int, newFunc NewPluginRequest, handler Handler, tl
}
resp := handler(r)
buf, _ = json.Marshal(resp)
log.Trace("plugin response: %s", string(buf))
log.Tracef("plugin response: %s", string(buf))
_, _ = w.Write(buf)
})),
)

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